Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: build

on:
push:
branches: [master]
pull_request:
workflow_dispatch:

jobs:
build:
name: ${{ matrix.os }} / SDL ${{ matrix.sdl }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
sdl: [1, 2]
steps:
- uses: actions/checkout@v4

- name: Install SDL (Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt-get update -qq
sudo apt-get install -y libsdl1.2-dev libsdl2-dev

- name: Install SDL (macOS)
if: runner.os == 'macOS'
run: brew install sdl12-compat sdl2

- name: Build
run: make SDL=${{ matrix.sdl }}

- name: Build z80emu CPU core
run: make clean && make CPU=z80emu SDL=${{ matrix.sdl }}

- name: CPU tests
run: make test
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
obj
objhtml
zxem
maketables
zxem.html
zxem.js
zxem.data
maketables
tests/zxtest
tests/zxtest.log
7 changes: 0 additions & 7 deletions .travis.yml

This file was deleted.

3 changes: 2 additions & 1 deletion INSTALL
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
For Linux or Mac, just type "make". It will compile the example zextest.
For Linux or Mac, install SDL 1.2 or SDL2 and type "make" to build zxem.
See README.md for the build options (SDL=2, DEBUG=1, PLAT=HTML, make test).

For Windows, open a Visual C++ command prompt and then type:

Expand Down
190 changes: 93 additions & 97 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,136 +1,132 @@
# ZXEM MAKEFILE
OLEVEL = -O3
CFLAGS = -Isrc/zxem -Isrc/osdep -Isrc/cpu -Wall -pedantic $(OLEVEL) -fomit-frame-pointer
SDL = 1
ZCC = $(ZCC)
#CPU = z80emu
#CPU = mz80
#CPU = deadz80
CPU = z80core
#
# make native build (SDL 1.2, z80core CPU)
# make SDL=2 build against SDL2
# make SDL=0 build with the dummy (no video) backend
# make DEBUG=1 debug build (-O0 -g)
# make PLAT=HTML Emscripten build (zxem.html)
# make test build and run the CPU test suite (z80emu core)

## Config

# CPU core: z80core (default), z80emu, mz80 (mz80 has issues on 64-bit)
CPU ?= z80core
SDL ?= 1
PLAT ?= NATIVE

TARGET = zxem
TEST_TARGET = tests/zxtest
OBJDIR = obj
ifndef PLAT
PLAT = NATIVE
endif

CPPFLAGS += -Isrc/zxem -Isrc/osdep -Isrc/cpu
WARNINGS = -Wall -pedantic
CFLAGS += $(WARNINGS) -fomit-frame-pointer
CXXFLAGS += $(WARNINGS) -std=c++11 -fomit-frame-pointer

ifdef DEBUG
OLEVEL = -O0 -g
else
OLEVEL = -O2
endif
CFLAGS += $(OLEVEL)
CXXFLAGS += $(OLEVEL)

OSD_SOURCE = src/osdep/dummy.c

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
endif

## Platform specific config

ifeq ($(PLAT), HTML)
ZCC = emcc
CC = emcc
CXX = em++
AR = emar
OSDFLAGS = -s USE_SDL=$(SDL)
OSDLIBS =
OLEVEL += -s ASM_JS=1
LINKFLAGS = $(OSDFLAGS) $(OLEVEL) --preload-files roms/ --preload-files scr/ --emrun
TARGET := $(TARGET).html
OBJDIR = objhtml
SDLFLAGS = -s USE_SDL=$(SDL)
OSDLIBS =
LINKFLAGS += $(SDLFLAGS) --preload-file roms --preload-file scr --emrun
TARGET := $(TARGET).html
else
OBJDIR = obj
endif

ifeq ($(CPU), z80emu)
CPUOBJ = $(OBJDIR)/z80emu.o
CPUINTC = src/cpu/z80emu/cpuintf.c
endif
## OS dependent (video/input) backend

ifeq ($(CPU), mz80)
CPUOBJ = $(OBJDIR)/mz80.o
CPUINTC = src/cpu/mz80/cpuintf.c
ifeq ($(SDL), 1)
OSD_SOURCE = src/osdep/sdl1.2.c
ifneq ($(PLAT), HTML)
SDLFLAGS = $(shell sdl-config --cflags)
OSDLIBS = $(shell sdl-config --libs)
endif

ifeq ($(CPU), deadz80)
CPUOBJ = $(OBJDIR)/deadz80.o
CPUINTC = src/cpu/deadz80/cpuintf.c
else ifeq ($(SDL), 2)
OSD_SOURCE = src/osdep/sdl2.c
ifneq ($(PLAT), HTML)
SDLFLAGS = $(shell sdl2-config --cflags)
OSDLIBS = $(shell sdl2-config --libs)
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

OSD_SOURCE = src/osdep/dummy.c
endif

## Sources: every .c/.cpp in the selected CPU directory plus src/zxem.
## Helper programs (maketables, zextest) live in src/cpu/z80emu/util so
## they are not picked up here.

all: $(OBJDIR) $(TARGET)
CPUSRC := $(wildcard src/cpu/$(CPU)/*.c) $(wildcard src/cpu/$(CPU)/*.cpp)
ZXEMSRC := $(wildcard src/zxem/*.c)

$(OBJDIR):
mkdir $(OBJDIR)
obj_of = $(addprefix $(OBJDIR)/,$(addsuffix .o,$(subst /,_,$(patsubst src/%,%,$(basename $(1))))))

tables.h: maketables.c
$(ZCC) -Wall $< -o maketables
./maketables > $@
CPUOBJ := $(call obj_of,$(CPUSRC))
ZXEMOBJ := $(call obj_of,$(ZXEMSRC))
OSDOBJ := $(OBJDIR)/osdep.o
OBJECTS := $(ZXEMOBJ) $(CPUOBJ) $(OSDOBJ)

# 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 $@
HEADERS := $(wildcard src/*/*.h src/cpu/*/*.h)

# 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 $@
## Rules

# 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 $@
all: $(TARGET)

# Z80CORE - SUCCESS!
$(OBJDIR)/z80core_%.o: src/cpu/z80core/%.cpp
$(ZCC) $(CFLAGS) -c $< -o $@
$(OBJDIR):
mkdir -p $(OBJDIR)

#$(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
define compile_c
$(call obj_of,$(1)): $(1) $(HEADERS) | $(OBJDIR)
$$(CC) $$(CPPFLAGS) $$(CFLAGS) -c $$< -o $$@
endef
define compile_cxx
$(call obj_of,$(1)): $(1) $(HEADERS) | $(OBJDIR)
$$(CXX) $$(CPPFLAGS) $$(CXXFLAGS) -c $$< -o $$@
endef

$(OBJDIR)/zxem.o: src/zxem/zxem.c src/zxem/zxem.h src/osdep/osdep.h
$(ZCC) $(CFLAGS) $(OSDFLAGS) -c $< -o $@
$(foreach src,$(filter %.c,$(CPUSRC)) $(ZXEMSRC),$(eval $(call compile_c,$(src))))
$(foreach src,$(filter %.cpp,$(CPUSRC)),$(eval $(call compile_cxx,$(src))))

$(OBJDIR)/zxvid.o: src/zxem/zxvid.c src/zxem/zxem.h src/osdep/osdep.h
$(ZCC) $(CFLAGS) -c $< -o $@
$(OSDOBJ): $(OSD_SOURCE) $(HEADERS) | $(OBJDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) $(SDLFLAGS) -c $< -o $@

$(OBJDIR)/zxio.o: src/zxem/zxio.c src/zxem/zxem.h src/osdep/osdep.h
$(ZCC) $(CFLAGS) -c $< -o $@
# Link with the C++ driver so the C++ runtime is pulled in for z80core.
$(TARGET): $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) $(OSDLIBS) $(LINKFLAGS) -o $@

$(OBJDIR)/osdep.o: $(OSD_SOURCE) src/zxem/zxem.h src/osdep/osdep.h
$(ZCC) $(CFLAGS) $(OSDFLAGS) -c $(OSD_SOURCE) -o $@
## CPU test suite (exercises the z80emu core, whichever CPU zxem uses)

$(OBJDIR)/cpuintf.o: $(CPUINTC)
$(ZCC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/test_z80emu.o: src/cpu/z80emu/z80emu.c $(wildcard src/cpu/z80emu/*.h) | $(OBJDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

OBJECT_FILES = $(OBJDIR)/zxem.o $(CPUOBJ) $(OBJDIR)/zxvid.o $(OBJDIR)/zxio.o $(OBJDIR)/osdep.o $(OBJDIR)/cpuintf.o
$(TEST_TARGET): tests/cputest.c src/cpu/z80emu/z80emu.h $(OBJDIR)/test_z80emu.o
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(OBJDIR)/test_z80emu.o -o $@

$(TARGET): $(OBJECT_FILES)
$(ZCC) $(CFLAGS) $(OBJECT_FILES) $(OSDLIBS) $(LINKFLAGS) -o $@
# The suite stops at the first failure. The z80emu core currently passes the
# first $(KNOWN_PASSES) tests and fails at cb46 (BIT 0,(HL): undocumented
# flag bits 3/5 come from MEMPTR, which z80emu does not model). Fail the
# build if that number goes down, so new regressions are caught.
KNOWN_PASSES ?= 286

$(TEST_TARGET): tests/cputest.c src/cpu/z80emu/z80emu.h $(OBJDIR)/z80emu.o
$(ZCC) $(CFLAGS) $< $(OBJDIR)/z80emu.o -o $@
test: $(TEST_TARGET)
@(cd tests && ./zxtest > zxtest.log); \
passed=$$(grep -c PASSED tests/zxtest.log); \
echo "cputest: $$passed tests passed (expected at least $(KNOWN_PASSES))"; \
grep -B1 -A15 FAILED tests/zxtest.log | grep -v '^[ 0-9]*M[RW] ' ; \
test $$passed -ge $(KNOWN_PASSES)

clean:
rm -rf obj objhtml $(TARGET) zxem.html zxem.js zxem.data $(TEST_TARGET) tests/zxtest.log

clean:
rm $(OBJDIR)/*.o
rm $(TARGET)
.PHONY: all clean test
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,26 @@ ZXEMU is a free open source cross platform ZX Spectrum emulator, currently work

[Play online](http://js.mikedx.co.uk/zxem.html)

[![Build Status](https://travis-ci.org/MikeDX/z80emu.svg?branch=master)](https://travis-ci.org/MikeDX/z80emu)
[![build](https://github.com/MikeDX/z80emu/actions/workflows/build.yml/badge.svg)](https://github.com/MikeDX/z80emu/actions/workflows/build.yml)

## Building

Install SDL 1.2 (or SDL2) first:

- Ubuntu/Debian: `sudo apt-get install libsdl1.2-dev libsdl2-dev`
- macOS (Homebrew): `brew install sdl12-compat sdl2`

Then:

```
make # zxem with SDL 1.2
make SDL=2 # zxem with SDL2
make DEBUG=1 # debug build
make PLAT=HTML # Emscripten build (zxem.html)
make test # build and run the CPU test suite
```

Run `./zxem` from the repository root (it loads `roms/48k.rom`).

## TODO list
- [x] Working Z80 CPU Core
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/z80core/Z80Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class CZ80Core
typedef struct
{
void (CZ80Core::*function)(unsigned char opcode);
char* format;
const char* format;
} Z80Opcode;

typedef struct
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/z80core/Z80Core_CInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ typedef enum

//-----------------------------------------------------------------------------------------

void *Z80CORE_Create();
void *Z80CORE_Create(void);
void Z80CORE_Destroy(void *core);
void Z80CORE_Initialise(void *core, Z80CoreRead mem_read, Z80CoreWrite mem_write, Z80CoreRead io_read, Z80CoreWrite io_write, Z80CoreContention mem_contention_handling, Z80CoreContention io_contention_handling, int member_class);
void Z80CORE_Reset(void *core);
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 0 additions & 7 deletions src/cpu/z80emu/z80emu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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); \
Expand Down
2 changes: 1 addition & 1 deletion src/osdep/sdl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
* OSDEP file for SDL2
*/
#include <SDL2/SDL.h>
#include <SDL.h>
#include "osdep.h"
#include "zxem.h"

Expand Down
4 changes: 3 additions & 1 deletion tests/cputest.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ uint8_t writes[65536];
uint8_t reads[65536];

int total, running, debug;
int failed = 0;

uint8_t readbyte(uint16_t addr) {
// printf("Reading 0x%X\n",addr);
Expand Down Expand Up @@ -273,6 +274,7 @@ int main(int argc, char *argv[]) {

printf("TSTATES: %d : %d\n", etstates, tstates);

failed = 1;
break;
}
}
Expand All @@ -281,6 +283,6 @@ int main(int argc, char *argv[]) {
printf("DONE\n");

free(zxmem);
return 0;
return failed;

}
Loading