From 0714f266f526a3261eb5ed1274dce519f4e8639b Mon Sep 17 00:00:00 2001 From: cospplredman Date: Sat, 29 Jul 2023 17:03:01 -0500 Subject: [PATCH 1/5] fixed test build --- Makefile | 4 ++-- tests/cputest.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d261f04..7499075 100644 --- a/Makefile +++ b/Makefile @@ -127,10 +127,10 @@ OBJECT_FILES = $(OBJDIR)/zxem.o $(CPUOBJ) $(OBJDIR)/zxvid.o $(OBJDIR)/zxio.o $(O $(TARGET): $(OBJECT_FILES) $(ZCC) $(CFLAGS) $(OBJECT_FILES) $(OSDLIBS) $(LINKFLAGS) -o $@ -$(TEST_TARGET): tests/cputest.c z80emu.h $(OBJDIR)/z80emu.o +$(TEST_TARGET): $(TARGET) tests/cputest.c src/cpu/z80emu/z80emu.h $(OBJDIR)/z80emu.o $(ZCC) $(CFLAGS) $< $(OBJDIR)/z80emu.o -o $@ clean: rm $(OBJDIR)/*.o - rm $(TARGET) \ No newline at end of file + rm $(TARGET) diff --git a/tests/cputest.c b/tests/cputest.c index 0353fe5..0683bab 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1,6 +1,6 @@ // ZXTEST -#include "../z80emu.h" +#include "../src/cpu/z80emu/z80emu.h" #include #include #include From 504353d37ef014343a60724452f3e8b31b1470f6 Mon Sep 17 00:00:00 2001 From: cospplredman Date: Sat, 29 Jul 2023 17:05:12 -0500 Subject: [PATCH 2/5] fixed test build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7499075..a271e55 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,7 @@ OBJECT_FILES = $(OBJDIR)/zxem.o $(CPUOBJ) $(OBJDIR)/zxvid.o $(OBJDIR)/zxio.o $(O $(TARGET): $(OBJECT_FILES) $(ZCC) $(CFLAGS) $(OBJECT_FILES) $(OSDLIBS) $(LINKFLAGS) -o $@ -$(TEST_TARGET): $(TARGET) tests/cputest.c src/cpu/z80emu/z80emu.h $(OBJDIR)/z80emu.o +$(TEST_TARGET): tests/cputest.c src/cpu/z80emu/z80emu.h $(OBJDIR)/z80emu.o $(ZCC) $(CFLAGS) $< $(OBJDIR)/z80emu.o -o $@ From 38ecb724f72acbd6bdf4c7ce873779311724a515 Mon Sep 17 00:00:00 2001 From: cospplredman Date: Sat, 5 Aug 2023 21:15:00 -0500 Subject: [PATCH 3/5] moved z80emu utility files --- src/cpu/z80emu/util/maketables.c | 739 +++++++++++++++++++++++++++++++ src/cpu/z80emu/util/zextest.c | 172 +++++++ src/cpu/z80emu/util/zextest.h | 21 + src/cpu/z80emu/z80emu.h | 7 - 4 files changed, 932 insertions(+), 7 deletions(-) create mode 100644 src/cpu/z80emu/util/maketables.c create mode 100644 src/cpu/z80emu/util/zextest.c create mode 100644 src/cpu/z80emu/util/zextest.h diff --git a/src/cpu/z80emu/util/maketables.c b/src/cpu/z80emu/util/maketables.c new file mode 100644 index 0000000..d0a971e --- /dev/null +++ b/src/cpu/z80emu/util/maketables.c @@ -0,0 +1,739 @@ +/* maketables.c + * Instructions and flags tables generator. + * + * Copyright (c) 2012 Lin Ke-Fong + * + * This program is free, do whatever you want with it. + */ + +#include +#include +#include "z80emu.h" + +/* Encoding for indirect or indexed 8-bit memory operands. */ + +#define INDIRECT_HL 0x06 + +static void make_instruction_table (void); +static void make_cb_instruction_table (void); +static void make_ed_instruction_table (void); + +static void make_szyx_flags_table (void); +static void make_szyxp_flags_table (void); + +int main (void) +{ + printf("/* Generated file, see maketables.c. */\n\n"); + + make_instruction_table(); + putchar('\n'); + make_cb_instruction_table(); + putchar('\n'); + make_ed_instruction_table(); + putchar('\n'); + + make_szyx_flags_table(); + putchar('\n'); + make_szyxp_flags_table(); + + return EXIT_SUCCESS; +} + +/* Make single opcodes instruction table. */ + +static void make_instruction_table (void) +{ + int i, j, k; + char *s, *t; + static char *accumulator_operations[8] = { + + "ADD", + "ADC", + "SUB", + "SBC", + "AND", + "XOR", + "OR", + "CP", + + }; + + printf("static const unsigned char INSTRUCTION_TABLE[256] = {\n\n"); + for (k = 0; k < (1 << 6); k++) { + + putchar('\t'); + i = k >> 3; + j = k & 0x07; + switch (j) { + + /* Various opcodes. */ + + case 0x00: { + + static char *strings[8] = { + + "NOP", + "EX_AF_AF_PRIME", + "DJNZ_E", + "JR_E", + "JR_DD_E", + "JR_DD_E", + "JR_DD_E", + "JR_DD_E", + + }; + + s = strings[i]; + + break; + + } + + /* LD_RR_NN and ADD_HL_RR. */ + + case 0x01: { + + s = i & 1 ? "ADD_HL_RR" : "LD_RR_NN"; + break; + + } + + /* Indirect loading. */ + + case 0x02: { + + static char *strings[8] = { + + "LD_INDIRECT_BC_A", + "LD_A_INDIRECT_BC", + "LD_INDIRECT_DE_A", + "LD_A_INDIRECT_DE", + "LD_INDIRECT_NN_HL", + "LD_HL_INDIRECT_NN", + "LD_INDIRECT_NN_A", + "LD_A_INDIRECT_NN", + + }; + + s = strings[i]; + + break; + + } + + /* 16-bit INC and DEC. */ + + case 0x03: { + + s = i & 1 ? "DEC_RR" : "INC_RR"; + break; + + } + + /* 8-bit INC and DEC. */ + + case 0x04: + case 0x05: { + + if (j == 0x04) + + printf("INC_"); + + else + + printf("DEC_"); + + if (i == INDIRECT_HL) + + s = "INDIRECT_HL"; + + else + + s = "R"; + + break; + + } + + /* Immediate 8-bit loading. */ + + case 0x06: { + + if (i == INDIRECT_HL) + + s = "LD_INDIRECT_HL_N"; + + else + + s = "LD_R_N"; + + break; + + } + + /* RLCA, RRCA, RLA, RRA, DAA, CPL, SCF, and CCF. */ + + case 0x07: + default: { + + static char *strings[8] = { + + "RLCA", + "RRCA", + "RLA", + "RRA", + "DAA", + "CPL", + "SCF", + "CCF", + + }; + + s = strings[i]; + + break; + + } + + } + printf("%s,\n", s); + if (j == 0x07) + + putchar('\n'); + + } + + /* 8-bit loading and HALT. */ + + for (k = 0; k < (1 << 6); k++) { + + i = k >> 3; + j = k & 0x07; + if (i == j) { + + if (i == INDIRECT_HL) + + s = "HALT"; + + else + + s = "NOP"; + + printf("\t%s,\n", s); + + } else { + + if (i == INDIRECT_HL) + + s = "LD_INDIRECT_HL_"; + + else + + s = "LD_R_"; + + if (j == INDIRECT_HL) + + t = "INDIRECT_HL"; + + else + + t = "R"; + + printf("\t%s%s,\n", s, t); + + } + if (j == 0x07) + + putchar('\n'); + + } + + /* Operation on accumulator and register/memory. */ + + for (i = 0; i < (1 << 3); i++) { + + s = accumulator_operations[i]; + for (j = 0; j < (1 << 3); j++) { + + printf("\t%s_", s); + if (j == INDIRECT_HL) + + t = "INDIRECT_HL"; + + else + + t = "R"; + + printf("%s,\n", t); + + } + putchar('\n'); + + } + + for (k = 0; k < (1 << 6); k++) { + + putchar('\t'); + i = k >> 3; + j = k & 0x07; + switch (j) { + + /* RET CC. */ + + case 0x00: s = "RET_CC"; break; + + /* POP_SS, RET, EXX, JP_HL, and LD_SP_HL. */ + + case 0x01: { + + if (i & 1) { + + static char *strings[4] = { + + "RET", + "EXX", + "JP_HL", + "LD_SP_HL", + + }; + + s = strings[i >> 1]; + + } else + + s = "POP_SS"; + + break; + + } + + /* JP CC, NN. */ + + case 0x02: s = "JP_CC_NN"; break; + + /* Various opcodes. */ + + case 0x03: { + + static char *strings[8] = { + + "JP_NN", + "CB_PREFIX", + "OUT_N_A", + "IN_A_N", + "EX_INDIRECT_SP_HL", + "EX_DE_HL", + "DI", + "EI", + + }; + + s = strings[i]; + break; + + } + + /* CALL_CC_NN. */ + + case 0x04: s = "CALL_CC_NN"; break; + + /* PUSH_SS, CALL_NN, and prefixes. */ + + case 0x05: { + + if (i & 1) { + + static char *strings[4] = { + + "CALL_NN", + "DD_PREFIX", + "ED_PREFIX", + "FD_PREFIX", + + }; + + s = strings[i >> 1]; + + } else + + s = "PUSH_SS"; + + break; + + } + + /* Operation on accumulator and immediate. */ + + case 0x06: { + + printf("%s", accumulator_operations[i]); + s = "_N"; + + break; + + } + + /* RST_P. */ + + case 0x07: + default: s = "RST_P"; break; + + } + printf("%s,\n", s); + if (j == 0x07) + + putchar('\n'); + + } + printf("};\n"); +} + +/* Make 0xcb prefixed opcodes instruction table. */ + +static void make_cb_instruction_table (void) +{ + int i; + char *s; + + printf("static const unsigned char CB_INSTRUCTION_TABLE[256] = {\n\n"); + + /* Rotation/shift operations. */ + + for (i = 0; i < (1 << 6); i++) { + + static char *rotation_shift_operations[8] = { + + "RLC", + "RRC", + "RL", + "RR", + "SLA", + "SRA", + "SLL", + "SRL", + + }; + + printf("\t%s_", rotation_shift_operations[i >> 3]); + if ((i & 0x07) == INDIRECT_HL) + + s = "INDIRECT_HL"; + + else + + s = "R"; + + printf("%s,\n", s); + if ((i & 0x07) == 0x07) + + putchar('\n'); + + } + + /* BIT_B_R and BIT_B_INDIRECT_HL. */ + + for (i = 0; i < (1 << 6); i++) { + + if ((i & 0x07) == INDIRECT_HL) + + s = "BIT_B_INDIRECT_HL"; + + else + + s = "BIT_B_R"; + + printf("\t%s,\n", s); + if ((i & 0x07) == 0x07) + + putchar('\n'); + + } + + /* RES_B_R and RES_B_INDIRECT_HL. */ + + for (i = 0; i < (1 << 6); i++) { + + if ((i & 0x07) == INDIRECT_HL) + + s = "RES_B_INDIRECT_HL"; + + else + + s = "RES_B_R"; + + printf("\t%s,\n", s); + if ((i & 0x07) == 0x07) + + putchar('\n'); + + } + + /* SET_B_R and SET_B_INDIRECT_HL. */ + + for (i = 0; i < (1 << 6); i++) { + + if ((i & 0x07) == INDIRECT_HL) + + s = "SET_B_INDIRECT_HL"; + + else + + s = "SET_B_R"; + + printf("\t%s,\n", s); + if ((i & 0x07) == 0x07) + + putchar('\n'); + + } + + printf("};\n"); +} + +/* Make 0xed prefixed opcodes instruction table. */ + +static void make_ed_instruction_table (void) +{ + int i, j, k; + char *s, *t; + + printf("static const unsigned char ED_INSTRUCTION_TABLE[256] = {\n\n"); + + /* Undefined opcodes are catched and will execute as NOPs. */ + + for (i = 0; i < (1 << 6); i++) { + + printf("\tED_UNDEFINED,\n"); + if ((i & 0x07) == 0x07) + + putchar('\n'); + + } + + /* 0xed prefixed opcodes. */ + + for (k = 0; k < (1 << 6); k++) { + + i = k >> 3; + j = k & 0x07; + switch (j) { + + case 0x00: + case 0x01: { + + s = j ? "OUT_C_R" : "IN_R_C"; + t = ""; + break; + + } + + /* SBC_HL_RR and ADC_HL_RR. */ + + case 0x02: { + + s = i & 1 ? "ADC" : "SBC"; + t = "_HL_RR"; + break; + + } + + /* LD_INDIRECT_NN_RR and LD_RR_INDIRECT_NN. */ + + case 0x03: { + + s = "LD_"; + t = i & 1 + ? "RR_INDIRECT_NN" + : "INDIRECT_NN_RR"; + break; + + } + + /* NEG and IM_N. */ + + case 0x04: + case 0x06: { + + s = j == 0x04 ? "NEG" : "IM_N"; + t = ""; + break; + + } + + /* RETN and RETI. */ + + case 0x05: { + + s = "RETI_RETN"; + t = ""; + break; + + } + + /* Various opcodes. */ + + case 0x07: + default: { + + static char *strings[8] = { + + "LD_I_A_LD_R_A", + "LD_I_A_LD_R_A", + "LD_A_I_LD_A_R", + "LD_A_I_LD_A_R", + "RLD_RRD", + "RLD_RRD", + "ED_UNDEFINED", + "ED_UNDEFINED", + + }; + s = strings[i]; + t = ""; + break; + + } + + } + printf("\t%s%s,\n", s, t); + if ((j & 0x07) == 0x07) + + putchar('\n'); + + } + + /* Block instructions opcodes. */ + + for (k = 0; k < (1 << 6); k++) { + + static char *strings[4][4] = { + + { + + "LDI_LDD", + "CPI_CPD", + "INI_IND", + "OUTI_OUTD", + + }, + + { + + "LDI_LDD", + "CPI_CPD", + "INI_IND", + "OUTI_OUTD", + + }, + + { + + "LDIR_LDDR", + "CPIR_CPDR", + "INIR_INDR", + "OTIR_OTDR", + + }, + + { + + "LDIR_LDDR", + "CPIR_CPDR", + "INIR_INDR", + "OTIR_OTDR", + + }, + + }; + i = k >> 3; + j = k & 0x07; + if (i < 4 || j > 3) + + s = "ED_UNDEFINED"; + + else + + s = strings[i - 4][j]; + + printf("\t%s, \n", s); + if ((j & 0x07) == 0x07) + + putchar('\n'); + + } + + for (i = 0; i < (1 << 6); i++) { + + printf("\tED_UNDEFINED,\n"); + if ((i & 0x07) == 0x07) + + putchar('\n'); + + } + + printf("};\n"); +} + +/* Make S, Z, Y, and X flags table. */ + +static void make_szyx_flags_table (void) +{ + int i; + + printf("static const unsigned char SZYX_FLAGS_TABLE[256] = {\n"); + for (i = 0; i < 256; i++) { + + int r; + + r = i & (Z80_S_FLAG | Z80_Y_FLAG | Z80_X_FLAG); + r |= !i ? Z80_Z_FLAG : 0; + + if (!(i & 7)) + + printf("\n\t0x%02x, ", r); + + else + + printf("0x%02x, ", r); + + + } + printf("\n\n};\n"); +} + +/* Make S, Z, Y, X, and P flags table. */ + +static void make_szyxp_flags_table (void) +{ + int i; + + printf("static const unsigned char SZYXP_FLAGS_TABLE[256] = {\n"); + for (i = 0; i < 256; i++) { + + int j, p, r; + + j = i; + p = !0; + while (j) { + + if (j & 1) + + p = !p; + + j >>= 1; + + } + r = i & (Z80_S_FLAG | Z80_Y_FLAG | Z80_X_FLAG); + r |= !i ? Z80_Z_FLAG : 0; + r |= p ? Z80_PV_FLAG : 0; + + if (!(i & 7)) + + printf("\n\t0x%02x, ", r); + + else + + printf("0x%02x, ", r); + + } + printf("\n\n};\n"); +} diff --git a/src/cpu/z80emu/util/zextest.c b/src/cpu/z80emu/util/zextest.c new file mode 100644 index 0000000..2b5014e --- /dev/null +++ b/src/cpu/z80emu/util/zextest.c @@ -0,0 +1,172 @@ +/* zextest.c + * Example program using z80emu to run the zexall and zexdoc tests. This will + * check if the Z80 is correctly emulated. + * + * Copyright (c) 2012 Lin Ke-Fong + * Copyright (c) 2012 Chris Pressey + * + * This program is free, do whatever you want with it. + */ + +#include +#include +#include "z80emu.h" +#ifdef EMSCRIPTEN +#include +#endif +#include + + +#define Z80_CPU_SPEED 4000000 /* In Hz. */ +#ifdef EMSCRIPTEN +#define CYCLES_PER_STEP (Z80_CPU_SPEED) +#else +#define CYCLES_PER_STEP (Z80_CPU_SPEED / 50) +#endif + +#define MAXIMUM_STRING_LENGTH 100 + +unsigned char memory[1 << 16]; + +static void emulate (char *filename); + +int main (void) + +{ + emulate("testfiles/zexdoc.com"); + emulate("testfiles/zexall.com"); + return EXIT_SUCCESS; +} + +/* Emulate "zexdoc.com" or "zexall.com". */ +Z80_STATE state; +double total; +int stopped; + +void mainloop(void) { + total += Z80Emulate(&state, CYCLES_PER_STEP); + if (state.status & FLAG_STOP_EMULATION) +#ifdef EMSCRIPTEN + emscripten_cancel_main_loop(); +#else + stopped = 1; +#endif + +} + + +uint8_t readbyte(uint16_t addr) { + return memory[addr]; +} + +uint16_t readword(uint16_t addr) { + return memory[addr]|memory[addr+1]<<8; +} + +void writebyte(uint16_t addr, uint8_t data) { + memory[addr]=data; +} + +void writeword(uint16_t addr, uint16_t data) { + memory[addr]=data; + memory[addr+1]=data>>8; +} + +static void emulate (char *filename) + +{ + FILE *file; + long l; + + printf("Testing \"%s\"...\n", filename); + + if ((file = fopen(filename, "rb")) == NULL) { + + fprintf(stderr, "Can't open file!\n"); + exit(EXIT_FAILURE); + + } + + fseek(file, 0, SEEK_END); + l = ftell(file); + + fseek(file, 0, SEEK_SET); + fread(memory + 0x100, 1, l, file); + + fclose(file); + + /* Give this CPU some RAM */ + state.memory = memory; + state.readbyte = readbyte; + state.readword = readword; + state.writeword = writeword; + state.writebyte = writebyte; + + /* Patch memory of the program. Reset at 0x0000 is trapped by an OUT + * which will stop emulation. CP/M bdos call 5 is trapped by an IN. See + * Z80_INPUT_BYTE() and Z80_OUTPUT_BYTE() definitions in z80emu.h. + */ + + memory[0] = 0xd3; /* OUT N, A */ + memory[1] = 0x00; + + memory[5] = 0xdb; /* IN A, N */ + memory[6] = 0x00; + memory[7] = 0xc9; /* RET */ + + /* Emulate. */ + + Z80Reset(&state); + state.pc = 0x100; + total = 0.0; +#ifndef EMSCRIPTEN + stopped = 0; + for ( ; ; ) { + mainloop(); + if(stopped == 1) + break; + } +#else + emscripten_set_main_loop(mainloop,0,1); +#endif + + printf("\n%.0f cycle(s) emulated.\n" + "For a Z80 running at %.2fMHz, " + "that would be %d second(s) or %.2f hour(s).\n", + total, + Z80_CPU_SPEED / 1000000.0, + (int) (total / Z80_CPU_SPEED), + total / ((double) 3600 * Z80_CPU_SPEED)); +} + +/* Emulate CP/M bdos call 5 functions 2 (output character on screen) and 9 + * (output $-terminated string to screen). + */ + +void SystemCall (Z80_STATE *state) +{ + if (state->registers.byte[Z80_C] == 2) + + printf("%c", state->registers.byte[Z80_E]); + + else if (state->registers.byte[Z80_C] == 9) { + + int i, c; + + for (i = state->registers.word[Z80_DE], c = 0; + memory[i] != '$'; + i++) { + + printf("%c", memory[i & 0xffff]); + if (c++ > MAXIMUM_STRING_LENGTH) { + + fprintf(stderr, + "String to print is too long!\n"); + exit(EXIT_FAILURE); + + } + + } + + } +} diff --git a/src/cpu/z80emu/util/zextest.h b/src/cpu/z80emu/util/zextest.h new file mode 100644 index 0000000..0c5395b --- /dev/null +++ b/src/cpu/z80emu/util/zextest.h @@ -0,0 +1,21 @@ +/* zextest.h + * Header for zextest example. + * + * Copyright (c) 2012 Lin Ke-Fong + * + * This program is free, do whatever you want with it. + */ + +#ifndef __ZEXTEST_INCLUDED__ + +/* Additional Z80_STATE status flag to request emulation termination. */ + +#define FLAG_STOP_EMULATION (1 << 31) + +extern unsigned char memory[1 << 16]; + +extern void SystemCall (Z80_STATE *state); + +#define __ZEXTEST_INCLUDED__ + +#endif diff --git a/src/cpu/z80emu/z80emu.h b/src/cpu/z80emu/z80emu.h index fe73e7c..9e9eb56 100644 --- a/src/cpu/z80emu/z80emu.h +++ b/src/cpu/z80emu/z80emu.h @@ -248,13 +248,6 @@ typedef struct Z80_STATE_ { * register_table for 0xdd or 0xfd prefixes. */ -/* Here are macros for the zextest example. Read/write memory macros have been - * written for a linear 64k RAM. Input/output port macros are used to simulate - * system calls. - */ - -#include "zextest.h" - #define Z80_FETCH_BYTE(address, x) \ { \ (x) = state->readbyte(address); \ From 815f3f6f5338e1548f1fe6b619ab33bbf68130af Mon Sep 17 00:00:00 2001 From: cospplredman Date: Sat, 5 Aug 2023 21:16:28 -0500 Subject: [PATCH 4/5] moved z80emu utility files --- src/cpu/z80emu/maketables.c | 739 ------------------------------------ src/cpu/z80emu/zextest.c | 172 --------- src/cpu/z80emu/zextest.h | 21 - 3 files changed, 932 deletions(-) delete mode 100644 src/cpu/z80emu/maketables.c delete mode 100644 src/cpu/z80emu/zextest.c delete mode 100644 src/cpu/z80emu/zextest.h diff --git a/src/cpu/z80emu/maketables.c b/src/cpu/z80emu/maketables.c deleted file mode 100644 index d0a971e..0000000 --- a/src/cpu/z80emu/maketables.c +++ /dev/null @@ -1,739 +0,0 @@ -/* maketables.c - * Instructions and flags tables generator. - * - * Copyright (c) 2012 Lin Ke-Fong - * - * This program is free, do whatever you want with it. - */ - -#include -#include -#include "z80emu.h" - -/* Encoding for indirect or indexed 8-bit memory operands. */ - -#define INDIRECT_HL 0x06 - -static void make_instruction_table (void); -static void make_cb_instruction_table (void); -static void make_ed_instruction_table (void); - -static void make_szyx_flags_table (void); -static void make_szyxp_flags_table (void); - -int main (void) -{ - printf("/* Generated file, see maketables.c. */\n\n"); - - make_instruction_table(); - putchar('\n'); - make_cb_instruction_table(); - putchar('\n'); - make_ed_instruction_table(); - putchar('\n'); - - make_szyx_flags_table(); - putchar('\n'); - make_szyxp_flags_table(); - - return EXIT_SUCCESS; -} - -/* Make single opcodes instruction table. */ - -static void make_instruction_table (void) -{ - int i, j, k; - char *s, *t; - static char *accumulator_operations[8] = { - - "ADD", - "ADC", - "SUB", - "SBC", - "AND", - "XOR", - "OR", - "CP", - - }; - - printf("static const unsigned char INSTRUCTION_TABLE[256] = {\n\n"); - for (k = 0; k < (1 << 6); k++) { - - putchar('\t'); - i = k >> 3; - j = k & 0x07; - switch (j) { - - /* Various opcodes. */ - - case 0x00: { - - static char *strings[8] = { - - "NOP", - "EX_AF_AF_PRIME", - "DJNZ_E", - "JR_E", - "JR_DD_E", - "JR_DD_E", - "JR_DD_E", - "JR_DD_E", - - }; - - s = strings[i]; - - break; - - } - - /* LD_RR_NN and ADD_HL_RR. */ - - case 0x01: { - - s = i & 1 ? "ADD_HL_RR" : "LD_RR_NN"; - break; - - } - - /* Indirect loading. */ - - case 0x02: { - - static char *strings[8] = { - - "LD_INDIRECT_BC_A", - "LD_A_INDIRECT_BC", - "LD_INDIRECT_DE_A", - "LD_A_INDIRECT_DE", - "LD_INDIRECT_NN_HL", - "LD_HL_INDIRECT_NN", - "LD_INDIRECT_NN_A", - "LD_A_INDIRECT_NN", - - }; - - s = strings[i]; - - break; - - } - - /* 16-bit INC and DEC. */ - - case 0x03: { - - s = i & 1 ? "DEC_RR" : "INC_RR"; - break; - - } - - /* 8-bit INC and DEC. */ - - case 0x04: - case 0x05: { - - if (j == 0x04) - - printf("INC_"); - - else - - printf("DEC_"); - - if (i == INDIRECT_HL) - - s = "INDIRECT_HL"; - - else - - s = "R"; - - break; - - } - - /* Immediate 8-bit loading. */ - - case 0x06: { - - if (i == INDIRECT_HL) - - s = "LD_INDIRECT_HL_N"; - - else - - s = "LD_R_N"; - - break; - - } - - /* RLCA, RRCA, RLA, RRA, DAA, CPL, SCF, and CCF. */ - - case 0x07: - default: { - - static char *strings[8] = { - - "RLCA", - "RRCA", - "RLA", - "RRA", - "DAA", - "CPL", - "SCF", - "CCF", - - }; - - s = strings[i]; - - break; - - } - - } - printf("%s,\n", s); - if (j == 0x07) - - putchar('\n'); - - } - - /* 8-bit loading and HALT. */ - - for (k = 0; k < (1 << 6); k++) { - - i = k >> 3; - j = k & 0x07; - if (i == j) { - - if (i == INDIRECT_HL) - - s = "HALT"; - - else - - s = "NOP"; - - printf("\t%s,\n", s); - - } else { - - if (i == INDIRECT_HL) - - s = "LD_INDIRECT_HL_"; - - else - - s = "LD_R_"; - - if (j == INDIRECT_HL) - - t = "INDIRECT_HL"; - - else - - t = "R"; - - printf("\t%s%s,\n", s, t); - - } - if (j == 0x07) - - putchar('\n'); - - } - - /* Operation on accumulator and register/memory. */ - - for (i = 0; i < (1 << 3); i++) { - - s = accumulator_operations[i]; - for (j = 0; j < (1 << 3); j++) { - - printf("\t%s_", s); - if (j == INDIRECT_HL) - - t = "INDIRECT_HL"; - - else - - t = "R"; - - printf("%s,\n", t); - - } - putchar('\n'); - - } - - for (k = 0; k < (1 << 6); k++) { - - putchar('\t'); - i = k >> 3; - j = k & 0x07; - switch (j) { - - /* RET CC. */ - - case 0x00: s = "RET_CC"; break; - - /* POP_SS, RET, EXX, JP_HL, and LD_SP_HL. */ - - case 0x01: { - - if (i & 1) { - - static char *strings[4] = { - - "RET", - "EXX", - "JP_HL", - "LD_SP_HL", - - }; - - s = strings[i >> 1]; - - } else - - s = "POP_SS"; - - break; - - } - - /* JP CC, NN. */ - - case 0x02: s = "JP_CC_NN"; break; - - /* Various opcodes. */ - - case 0x03: { - - static char *strings[8] = { - - "JP_NN", - "CB_PREFIX", - "OUT_N_A", - "IN_A_N", - "EX_INDIRECT_SP_HL", - "EX_DE_HL", - "DI", - "EI", - - }; - - s = strings[i]; - break; - - } - - /* CALL_CC_NN. */ - - case 0x04: s = "CALL_CC_NN"; break; - - /* PUSH_SS, CALL_NN, and prefixes. */ - - case 0x05: { - - if (i & 1) { - - static char *strings[4] = { - - "CALL_NN", - "DD_PREFIX", - "ED_PREFIX", - "FD_PREFIX", - - }; - - s = strings[i >> 1]; - - } else - - s = "PUSH_SS"; - - break; - - } - - /* Operation on accumulator and immediate. */ - - case 0x06: { - - printf("%s", accumulator_operations[i]); - s = "_N"; - - break; - - } - - /* RST_P. */ - - case 0x07: - default: s = "RST_P"; break; - - } - printf("%s,\n", s); - if (j == 0x07) - - putchar('\n'); - - } - printf("};\n"); -} - -/* Make 0xcb prefixed opcodes instruction table. */ - -static void make_cb_instruction_table (void) -{ - int i; - char *s; - - printf("static const unsigned char CB_INSTRUCTION_TABLE[256] = {\n\n"); - - /* Rotation/shift operations. */ - - for (i = 0; i < (1 << 6); i++) { - - static char *rotation_shift_operations[8] = { - - "RLC", - "RRC", - "RL", - "RR", - "SLA", - "SRA", - "SLL", - "SRL", - - }; - - printf("\t%s_", rotation_shift_operations[i >> 3]); - if ((i & 0x07) == INDIRECT_HL) - - s = "INDIRECT_HL"; - - else - - s = "R"; - - printf("%s,\n", s); - if ((i & 0x07) == 0x07) - - putchar('\n'); - - } - - /* BIT_B_R and BIT_B_INDIRECT_HL. */ - - for (i = 0; i < (1 << 6); i++) { - - if ((i & 0x07) == INDIRECT_HL) - - s = "BIT_B_INDIRECT_HL"; - - else - - s = "BIT_B_R"; - - printf("\t%s,\n", s); - if ((i & 0x07) == 0x07) - - putchar('\n'); - - } - - /* RES_B_R and RES_B_INDIRECT_HL. */ - - for (i = 0; i < (1 << 6); i++) { - - if ((i & 0x07) == INDIRECT_HL) - - s = "RES_B_INDIRECT_HL"; - - else - - s = "RES_B_R"; - - printf("\t%s,\n", s); - if ((i & 0x07) == 0x07) - - putchar('\n'); - - } - - /* SET_B_R and SET_B_INDIRECT_HL. */ - - for (i = 0; i < (1 << 6); i++) { - - if ((i & 0x07) == INDIRECT_HL) - - s = "SET_B_INDIRECT_HL"; - - else - - s = "SET_B_R"; - - printf("\t%s,\n", s); - if ((i & 0x07) == 0x07) - - putchar('\n'); - - } - - printf("};\n"); -} - -/* Make 0xed prefixed opcodes instruction table. */ - -static void make_ed_instruction_table (void) -{ - int i, j, k; - char *s, *t; - - printf("static const unsigned char ED_INSTRUCTION_TABLE[256] = {\n\n"); - - /* Undefined opcodes are catched and will execute as NOPs. */ - - for (i = 0; i < (1 << 6); i++) { - - printf("\tED_UNDEFINED,\n"); - if ((i & 0x07) == 0x07) - - putchar('\n'); - - } - - /* 0xed prefixed opcodes. */ - - for (k = 0; k < (1 << 6); k++) { - - i = k >> 3; - j = k & 0x07; - switch (j) { - - case 0x00: - case 0x01: { - - s = j ? "OUT_C_R" : "IN_R_C"; - t = ""; - break; - - } - - /* SBC_HL_RR and ADC_HL_RR. */ - - case 0x02: { - - s = i & 1 ? "ADC" : "SBC"; - t = "_HL_RR"; - break; - - } - - /* LD_INDIRECT_NN_RR and LD_RR_INDIRECT_NN. */ - - case 0x03: { - - s = "LD_"; - t = i & 1 - ? "RR_INDIRECT_NN" - : "INDIRECT_NN_RR"; - break; - - } - - /* NEG and IM_N. */ - - case 0x04: - case 0x06: { - - s = j == 0x04 ? "NEG" : "IM_N"; - t = ""; - break; - - } - - /* RETN and RETI. */ - - case 0x05: { - - s = "RETI_RETN"; - t = ""; - break; - - } - - /* Various opcodes. */ - - case 0x07: - default: { - - static char *strings[8] = { - - "LD_I_A_LD_R_A", - "LD_I_A_LD_R_A", - "LD_A_I_LD_A_R", - "LD_A_I_LD_A_R", - "RLD_RRD", - "RLD_RRD", - "ED_UNDEFINED", - "ED_UNDEFINED", - - }; - s = strings[i]; - t = ""; - break; - - } - - } - printf("\t%s%s,\n", s, t); - if ((j & 0x07) == 0x07) - - putchar('\n'); - - } - - /* Block instructions opcodes. */ - - for (k = 0; k < (1 << 6); k++) { - - static char *strings[4][4] = { - - { - - "LDI_LDD", - "CPI_CPD", - "INI_IND", - "OUTI_OUTD", - - }, - - { - - "LDI_LDD", - "CPI_CPD", - "INI_IND", - "OUTI_OUTD", - - }, - - { - - "LDIR_LDDR", - "CPIR_CPDR", - "INIR_INDR", - "OTIR_OTDR", - - }, - - { - - "LDIR_LDDR", - "CPIR_CPDR", - "INIR_INDR", - "OTIR_OTDR", - - }, - - }; - i = k >> 3; - j = k & 0x07; - if (i < 4 || j > 3) - - s = "ED_UNDEFINED"; - - else - - s = strings[i - 4][j]; - - printf("\t%s, \n", s); - if ((j & 0x07) == 0x07) - - putchar('\n'); - - } - - for (i = 0; i < (1 << 6); i++) { - - printf("\tED_UNDEFINED,\n"); - if ((i & 0x07) == 0x07) - - putchar('\n'); - - } - - printf("};\n"); -} - -/* Make S, Z, Y, and X flags table. */ - -static void make_szyx_flags_table (void) -{ - int i; - - printf("static const unsigned char SZYX_FLAGS_TABLE[256] = {\n"); - for (i = 0; i < 256; i++) { - - int r; - - r = i & (Z80_S_FLAG | Z80_Y_FLAG | Z80_X_FLAG); - r |= !i ? Z80_Z_FLAG : 0; - - if (!(i & 7)) - - printf("\n\t0x%02x, ", r); - - else - - printf("0x%02x, ", r); - - - } - printf("\n\n};\n"); -} - -/* Make S, Z, Y, X, and P flags table. */ - -static void make_szyxp_flags_table (void) -{ - int i; - - printf("static const unsigned char SZYXP_FLAGS_TABLE[256] = {\n"); - for (i = 0; i < 256; i++) { - - int j, p, r; - - j = i; - p = !0; - while (j) { - - if (j & 1) - - p = !p; - - j >>= 1; - - } - r = i & (Z80_S_FLAG | Z80_Y_FLAG | Z80_X_FLAG); - r |= !i ? Z80_Z_FLAG : 0; - r |= p ? Z80_PV_FLAG : 0; - - if (!(i & 7)) - - printf("\n\t0x%02x, ", r); - - else - - printf("0x%02x, ", r); - - } - printf("\n\n};\n"); -} diff --git a/src/cpu/z80emu/zextest.c b/src/cpu/z80emu/zextest.c deleted file mode 100644 index 2b5014e..0000000 --- a/src/cpu/z80emu/zextest.c +++ /dev/null @@ -1,172 +0,0 @@ -/* zextest.c - * Example program using z80emu to run the zexall and zexdoc tests. This will - * check if the Z80 is correctly emulated. - * - * Copyright (c) 2012 Lin Ke-Fong - * Copyright (c) 2012 Chris Pressey - * - * This program is free, do whatever you want with it. - */ - -#include -#include -#include "z80emu.h" -#ifdef EMSCRIPTEN -#include -#endif -#include - - -#define Z80_CPU_SPEED 4000000 /* In Hz. */ -#ifdef EMSCRIPTEN -#define CYCLES_PER_STEP (Z80_CPU_SPEED) -#else -#define CYCLES_PER_STEP (Z80_CPU_SPEED / 50) -#endif - -#define MAXIMUM_STRING_LENGTH 100 - -unsigned char memory[1 << 16]; - -static void emulate (char *filename); - -int main (void) - -{ - emulate("testfiles/zexdoc.com"); - emulate("testfiles/zexall.com"); - return EXIT_SUCCESS; -} - -/* Emulate "zexdoc.com" or "zexall.com". */ -Z80_STATE state; -double total; -int stopped; - -void mainloop(void) { - total += Z80Emulate(&state, CYCLES_PER_STEP); - if (state.status & FLAG_STOP_EMULATION) -#ifdef EMSCRIPTEN - emscripten_cancel_main_loop(); -#else - stopped = 1; -#endif - -} - - -uint8_t readbyte(uint16_t addr) { - return memory[addr]; -} - -uint16_t readword(uint16_t addr) { - return memory[addr]|memory[addr+1]<<8; -} - -void writebyte(uint16_t addr, uint8_t data) { - memory[addr]=data; -} - -void writeword(uint16_t addr, uint16_t data) { - memory[addr]=data; - memory[addr+1]=data>>8; -} - -static void emulate (char *filename) - -{ - FILE *file; - long l; - - printf("Testing \"%s\"...\n", filename); - - if ((file = fopen(filename, "rb")) == NULL) { - - fprintf(stderr, "Can't open file!\n"); - exit(EXIT_FAILURE); - - } - - fseek(file, 0, SEEK_END); - l = ftell(file); - - fseek(file, 0, SEEK_SET); - fread(memory + 0x100, 1, l, file); - - fclose(file); - - /* Give this CPU some RAM */ - state.memory = memory; - state.readbyte = readbyte; - state.readword = readword; - state.writeword = writeword; - state.writebyte = writebyte; - - /* Patch memory of the program. Reset at 0x0000 is trapped by an OUT - * which will stop emulation. CP/M bdos call 5 is trapped by an IN. See - * Z80_INPUT_BYTE() and Z80_OUTPUT_BYTE() definitions in z80emu.h. - */ - - memory[0] = 0xd3; /* OUT N, A */ - memory[1] = 0x00; - - memory[5] = 0xdb; /* IN A, N */ - memory[6] = 0x00; - memory[7] = 0xc9; /* RET */ - - /* Emulate. */ - - Z80Reset(&state); - state.pc = 0x100; - total = 0.0; -#ifndef EMSCRIPTEN - stopped = 0; - for ( ; ; ) { - mainloop(); - if(stopped == 1) - break; - } -#else - emscripten_set_main_loop(mainloop,0,1); -#endif - - printf("\n%.0f cycle(s) emulated.\n" - "For a Z80 running at %.2fMHz, " - "that would be %d second(s) or %.2f hour(s).\n", - total, - Z80_CPU_SPEED / 1000000.0, - (int) (total / Z80_CPU_SPEED), - total / ((double) 3600 * Z80_CPU_SPEED)); -} - -/* Emulate CP/M bdos call 5 functions 2 (output character on screen) and 9 - * (output $-terminated string to screen). - */ - -void SystemCall (Z80_STATE *state) -{ - if (state->registers.byte[Z80_C] == 2) - - printf("%c", state->registers.byte[Z80_E]); - - else if (state->registers.byte[Z80_C] == 9) { - - int i, c; - - for (i = state->registers.word[Z80_DE], c = 0; - memory[i] != '$'; - i++) { - - printf("%c", memory[i & 0xffff]); - if (c++ > MAXIMUM_STRING_LENGTH) { - - fprintf(stderr, - "String to print is too long!\n"); - exit(EXIT_FAILURE); - - } - - } - - } -} diff --git a/src/cpu/z80emu/zextest.h b/src/cpu/z80emu/zextest.h deleted file mode 100644 index 0c5395b..0000000 --- a/src/cpu/z80emu/zextest.h +++ /dev/null @@ -1,21 +0,0 @@ -/* zextest.h - * Header for zextest example. - * - * Copyright (c) 2012 Lin Ke-Fong - * - * This program is free, do whatever you want with it. - */ - -#ifndef __ZEXTEST_INCLUDED__ - -/* Additional Z80_STATE status flag to request emulation termination. */ - -#define FLAG_STOP_EMULATION (1 << 31) - -extern unsigned char memory[1 << 16]; - -extern void SystemCall (Z80_STATE *state); - -#define __ZEXTEST_INCLUDED__ - -#endif From 9706691f19074c56e3735cbe4cd4109aebdb76ba Mon Sep 17 00:00:00 2001 From: cospplredman Date: Sat, 5 Aug 2023 21:17:25 -0500 Subject: [PATCH 5/5] updated Makefile --- Makefile | 168 ++++++++++++++++++++----------------------------------- 1 file changed, 62 insertions(+), 106 deletions(-) diff --git a/Makefile b/Makefile index a271e55..adb1307 100644 --- a/Makefile +++ b/Makefile @@ -1,136 +1,92 @@ # ZXEM MAKEFILE -OLEVEL = -O3 -CFLAGS = -Isrc/zxem -Isrc/osdep -Isrc/cpu -Wall -pedantic $(OLEVEL) -fomit-frame-pointer -SDL = 1 -ZCC = $(ZCC) + +## config +CFLAGS = -Isrc/zxem -Isrc/osdep -Isrc/cpu -Wall -Wextra -pedantic -fomit-frame-pointer +CXXFLAGS = -fpermissive + +ifdef DEBUG +CFLAGS += -g -O0 +else +CFLAGS += -O2 +endif + +# MULTI CPU CORE! #CPU = z80emu + +# MZ80 - Issues on 64bit :( +# MZ80 BROKEN! #CPU = mz80 -#CPU = deadz80 + +# Z80CORE CPU = z80core TARGET = zxem TEST_TARGET = tests/zxtest -OBJDIR = obj -ifndef PLAT -PLAT = NATIVE -endif - -ifdef DEBUG -OLEVEL = -O0 -g -endif -OSD_SOURCE = src/osdep/dummy.c + +## Platform specific config -ifdef SDL -ifeq ($(SDL), 1) -OSD_SOURCE = src/osdep/sdl1.2.c -OSDFLAGS = $(shell sdl-config --cflags) -OSDLIBS = $(shell sdl-config --libs) -endif -ifeq ($(SDL), 2) -OSD_SOURCE = src/osdep/sdl2.c -OSDFLAGS = $(shell sdl2-config --cflags) -OSDLIBS = $(shell sdl2-config --libs) -endif +PLAT ?= NATIVE +ifeq ($(PLAT), NATIVE) +CC ?= gcc +CXX ?= g++ +OBJDIR = obj endif - - ifeq ($(PLAT), HTML) -ZCC = emcc +CXX = em++ +CC = emcc +OBJDIR = objhtml + AR = emar -OSDFLAGS = -s USE_SDL=$(SDL) +CFLAGS += -s ASM_JS=1 -s USE_SDL=$(SDL) +LINKFLAGS += --preload-file ./roms --emrun OSDLIBS = -OLEVEL += -s ASM_JS=1 -LINKFLAGS = $(OSDFLAGS) $(OLEVEL) --preload-files roms/ --preload-files scr/ --emrun TARGET := $(TARGET).html -OBJDIR = objhtml endif -ifeq ($(CPU), z80emu) -CPUOBJ = $(OBJDIR)/z80emu.o -CPUINTC = src/cpu/z80emu/cpuintf.c -endif + +## make Rules -ifeq ($(CPU), mz80) -CPUOBJ = $(OBJDIR)/mz80.o -CPUINTC = src/cpu/mz80/cpuintf.c -endif +all: $(OBJDIR) $(TARGET) -ifeq ($(CPU), deadz80) -CPUOBJ = $(OBJDIR)/deadz80.o -CPUINTC = src/cpu/deadz80/cpuintf.c -endif - -ifeq ($(CPU), z80core) -CPUOBJ = $(OBJDIR)/z80core_Z80Core.o $(OBJDIR)/z80core_Z80Core_CBOpcodes.o $(OBJDIR)/z80core_Z80Core_DDCB_FDCBOpcodes.o $(OBJDIR)/z80core_Z80Core_DDOpcodes.o $(OBJDIR)/z80core_Z80Core_EDOpcodes.o $(OBJDIR)/z80core_Z80Core_FDOpcodes.o $(OBJDIR)/z80core_Z80Core_MainOpcodes.o $(OBJDIR)/z80core_Z80Core_CInterface.o -CPUINTC = src/cpu/z80core/cpuintf.c - -# add permissive for initialising members in class definitions (Z80Core.h) -CFLAGS += -fpermissive - -#compile as c++ when using z80 core -ifeq ($(PLAT), HTML) -ZCC = em++ -else -ZCC = $(CXX) -endif - -endif - - -all: $(OBJDIR) $(TARGET) +clean: + rm -rf $(OBJDIR)/* $(TARGET) $(TEST_TARGET) $(OBJDIR): mkdir $(OBJDIR) -tables.h: maketables.c - $(ZCC) -Wall $< -o maketables - ./maketables > $@ - -# MULTI CPU CORE! -# Z80EMU - BROKEN -$(OBJDIR)/z80emu.o: src/cpu/z80emu/z80emu.c src/cpu/z80emu/z80emu.h src/cpu/z80emu/instructions.h src/cpu/z80emu/macros.h src/cpu/z80emu/tables.h - $(ZCC) $(CFLAGS) -c $< -o $@ - -# MZ80 - Issues on 64bit :( -$(OBJDIR)/mz80.o: src/cpu/mz80/mz80.c src/cpu/mz80/mz80.h src/cpu/cpuintf.h - $(ZCC) $(CFLAGS) -c $< -o $@ - -# DEADZ80 - Dead? -$(OBJDIR)/deadz80.o: src/cpu/deadz80/deadz80.c src/cpu/deadz80/deadz80.h src/cpu/deadz80/opcodes.h src/cpu/cpuintf.h - $(ZCC) $(CFLAGS) -c $< -o $@ - -# Z80CORE - SUCCESS! -$(OBJDIR)/z80core_%.o: src/cpu/z80core/%.cpp - $(ZCC) $(CFLAGS) -c $< -o $@ - -#$(OBJDIR)/z80core.a: src/cpu/z80core/Z80Core.o src/cpu/z80core/Z80Core_CBOpcodes.o src/cpu/z80core/Z80Core_DDCB_FDCBOpcodes.o src/cpu/z80core/Z80Core_DDOpcodes.o src/cpu/z80core/Z80Core_EDOpcodes.o src/cpu/z80core/Z80Core_FDOpcodes.o src/cpu/z80core/Z80Core_MainOpcodes.o -# $(AR) cr $@ src/cpu/z80core/*.o - -$(OBJDIR)/zxem.o: src/zxem/zxem.c src/zxem/zxem.h src/osdep/osdep.h - $(ZCC) $(CFLAGS) $(OSDFLAGS) -c $< -o $@ -$(OBJDIR)/zxvid.o: src/zxem/zxvid.c src/zxem/zxem.h src/osdep/osdep.h - $(ZCC) $(CFLAGS) -c $< -o $@ +### SDL -$(OBJDIR)/zxio.o: src/zxem/zxio.c src/zxem/zxem.h src/osdep/osdep.h - $(ZCC) $(CFLAGS) -c $< -o $@ - -$(OBJDIR)/osdep.o: $(OSD_SOURCE) src/zxem/zxem.h src/osdep/osdep.h - $(ZCC) $(CFLAGS) $(OSDFLAGS) -c $(OSD_SOURCE) -o $@ +SDL ?= 1 +ifdef SDL +ifeq ($(SDL), 1) +OSDLIBS ?= $(shell sdl-config --libs) +$(OBJDIR)/osdep.o: src/osdep/sdl1.2.c + $(CC) $(CFLAGS) $(shell sdl-config --cflags) -c $< -o $@ +endif +ifeq ($(SDL), 2) +OSDLIBS ?= $(shell sdl2-config --libs) +$(OBJDIR)/osdep.o: src/osdep/sdl2.c + $(CC) $(CFLAGS) $(shell sdl2-config --cflags) -c $< -o $@ +endif +else +$(OBJDIR)/osdep.o: src/osdep/dummy.c + $(CC) $(CFLAGS) -c $< -o $@ +endif -$(OBJDIR)/cpuintf.o: $(CPUINTC) - $(ZCC) $(CFLAGS) -c $< -o $@ +CPUSRC := $(wildcard ./src/cpu/$(CPU)/*.c) $(wildcard ./src/cpu/$(CPU)/*.cpp) +CPUOBJ := $(CPUSRC:.cpp=.o) +CPUOBJ := $(CPUOBJ:.c=.o) -OBJECT_FILES = $(OBJDIR)/zxem.o $(CPUOBJ) $(OBJDIR)/zxvid.o $(OBJDIR)/zxio.o $(OBJDIR)/osdep.o $(OBJDIR)/cpuintf.o +ZXEMSRC := $(wildcard ./src/zxem/*.c) +ZXEMOBJ := $(ZXEMSRC:.c=.o) -$(TARGET): $(OBJECT_FILES) - $(ZCC) $(CFLAGS) $(OBJECT_FILES) $(OSDLIBS) $(LINKFLAGS) -o $@ +$(TARGET): $(OBJDIR)/zxem.a($(ZXEMOBJ)) $(OBJDIR)/$(CPU).a($(CPUOBJ)) $(OBJDIR)/osdep.o + $(CXX) $(CFLAGS) $(CXXFLAGS) $^ $(OSDLIBS) $(LINKFLAGS) -o $@ +#TODO test is z80emu specific $(TEST_TARGET): tests/cputest.c src/cpu/z80emu/z80emu.h $(OBJDIR)/z80emu.o - $(ZCC) $(CFLAGS) $< $(OBJDIR)/z80emu.o -o $@ - + $(CC) $(CFLAGS) $< $(OBJDIR)/z80emu.o -o $@ -clean: - rm $(OBJDIR)/*.o - rm $(TARGET) +.PHONY: clean all