Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyler Stachecki committed Mar 8, 2014
0 parents commit 2f3aded
Show file tree
Hide file tree
Showing 34 changed files with 2,119 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
@@ -0,0 +1,9 @@
# Other data.
/data

# Build files.
/build

# Swap files.
*.swp

35 changes: 35 additions & 0 deletions CMakeLists.txt
@@ -0,0 +1,35 @@
#
# CEN64: Cycle-Accurate Nintendo 64 Simulator.
# Copyright (C) 2014, Tyler J. Stachecki.
#
# This file is subject to the terms and conditions defined in
# 'LICENSE', which is part of this source code package.
#

cmake_minimum_required(VERSION 2.6)
project(cen64)

if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU")
set(CMAKE_C_FLAGS "-Wall -Wextra -std=c99 -D_POSIX_SOURCE")

set(CMAKE_C_FLAGS_DEBUG "-ggdb3 -g3 -O0")
set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Og")
endif ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU")

include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/bus)
include_directories(${PROJECT_SOURCE_DIR}/pif)
include_directories(${PROJECT_SOURCE_DIR}/vr4300)

# Glob all the files together.
file(GLOB BUS_SOURCES ${PROJECT_SOURCE_DIR}/bus/*.c)
file(GLOB CEN64_SOURCES ${PROJECT_SOURCE_DIR}/*.c)
file(GLOB PIF_SOURCES ${PROJECT_SOURCE_DIR}/pif/*.c)
file(GLOB VR4300_SOURCES ${PROJECT_SOURCE_DIR}/vr4300/*.c)

# Create the executable.
add_executable(cen64 ${CEN64_SOURCES} ${BUS_SOURCES} ${PIF_SOURCES}
${VR4300_SOURCES})

25 changes: 25 additions & 0 deletions LICENSE
@@ -0,0 +1,25 @@
Copyright (c) 2014, Tyler J. Stachecki
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Tyler J. Stachecki nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL TYLER J. STACHECKI BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

31 changes: 31 additions & 0 deletions README.md
@@ -0,0 +1,31 @@
<p align="center">
<img src="/assets/logo.png" />
</p>

# About

This is my pet project. It's something I pick up whenever I get bored. To me,
what Nintendo and SGI did with this console is nothing short of amazing. The
ingenuity and design of the hardware was well-ahead of it's time, and it is
an absolute blast to reverse-engineer and study. I started this project in
order to learn more about what _really_ went on at the hardware level back in
the (good old) days.

That being said, I've also grown tired of people complaining that "cycle
accurate simulation on N-gen consoles is impossible." Not to be a bigot, but
no, it's not. Is it hard to write a simulator that is capable of running fast
enough to emulate a 93.75MHz processor on modern machines? Absolutely. Is it
impossible? No, certainly not. It just takes time. Programming is an art,
and like anything else, it takes time if done well.

Getting back on track: this simulator attempts to be everything that every
other emulator hoped to be, but never quite attained due to... emulation. My
hopes are that properly simulating things at the cycle and pixel-accurate level
will preserve the original fidelity of the work that so many companies put
out.

Thank you to every single one of you developers for filling my childhood
with excellent memories. I'd also like to thank the community on all their
hard work and effort spent reverse-engineering this little gem. Without
further ado...

1 change: 1 addition & 0 deletions VERSION
@@ -0,0 +1 @@
0.3
Binary file added assets/logo-small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions bus/controller.c
@@ -0,0 +1,36 @@
//
// bus/controller.c: System bus controller.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//

#include "common.h"
#include "bus/controller.h"
#include "pif/controller.h"

// Initializes the bus component.
int bus_init(struct bus_controller *bus) {
bus->num_requests = 0;
bus->rq_head = 0;
bus->rq_tail = 0;

return 0;
}

// Issues a read request to the bus.
unsigned bus_read_word(struct bus_controller *bus,
uint32_t address, uint32_t *word) {

if (address >= 0x1FC00000 && address < 0x1FC07C00)
return read_pifrom(bus->pif, word, address & 0xFFC);

printf("bus_read_word: Failed to access: 0x%.8X\n", address);
abort();

return 0;
}

31 changes: 31 additions & 0 deletions bus/controller.h
@@ -0,0 +1,31 @@
//
// bus/controller.h: System bus controller.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//

#ifndef __bus_controller_h__
#define __bus_controller_h__
#define BUS_REQUEST_QUEUE_SIZE 8

struct bus_request;
struct vr4300;

struct bus_controller {
struct bus_request *rq[BUS_REQUEST_QUEUE_SIZE];
unsigned num_requests, rq_head, rq_tail;

struct pif_controller *pif;
struct vr4300 *vr4300;
};

int bus_init(struct bus_controller *bus);
unsigned bus_read_word(struct bus_controller *bus,
uint32_t address, uint32_t *word);

#endif

32 changes: 32 additions & 0 deletions cen64.c
@@ -0,0 +1,32 @@
//
// cen64.c: CEN64 entry point.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//

#include "common.h"
#include "device.h"

int main(int argc, const char *argv[]) {
struct cen64_device *device;

if (argc < 2) {
printf("%s <pifrom.bin>\n", argv[0]);
return 0;
}

if ((device = device_create(argv[1])) == NULL) {
printf("Failed to create a device.\n");
return 1;
}

device_run(device);

device_destroy(device);
return 0;
}

86 changes: 86 additions & 0 deletions common.h
@@ -0,0 +1,86 @@
//
// common.h: Common definitions and such.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//

#ifndef __common_h__
#define __common_h__

#ifdef _MSC_VER
#define inline _inline
#endif

#ifndef __cplusplus
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#else
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <cstdint>
#include <cstdio>
#include <cstring>
#endif

#ifndef _MSC_VER
#ifndef __cplusplus
#include <stdbool.h>
#else
#include <cstdbool>
#endif

#else
typedef char bool;
#define false 0
#define true 1
#endif

#ifndef NDEBUG
#ifndef __cplusplus
#include <stdio.h>
#else
#include <cstdio>
#endif
#endif

#define CACHE_LINE_SIZE 64

// Define cen64_align().
#ifdef _MSC_VER
#define cen64_align(decl, value) __declspec(align(value)) decl

#elif (defined __GNUC__)
#define cen64_align(decl, value) decl __attribute__ ((aligned(value)))

#else
#define cen64_align(decl, value) decl value
#endif

// Define likely()/unlikely().
#ifdef __GNUC__
#define likely(expr) __builtin_expect(!!(expr), !0)
#define unlikely(expr) __builtin_expect(!!(expr), 0)

#else
#define likely(expr) expr
#define unlikely(expr) expr
#endif

// Define unused().
#ifdef __GNUC__
#define unused(decl) __attribute__((unused)) decl
#else
#define unused(decl) decl
#endif

#endif

97 changes: 97 additions & 0 deletions device.c
@@ -0,0 +1,97 @@
//
// device.c: CEN64 device container.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//

#include "common.h"
#include "device.h"
#include "pif/controller.h"

// Loads the PIFROM from a file into memory.
static int load_pifrom(const char *file, uint8_t *rom) {
int status = 0;
size_t i, last;
FILE *f;

if ((f = fopen(file, "rb")) == NULL) {
printf("load_pifrom: Failed to open: %s\n", file);
return -1;
}

for (i = 0; i < PIFROM_SIZE; i += last) {
last = fread(rom + i, 1, PIFROM_SIZE - i, f);

if (feof(f)) {
printf("load_pifrom: ROM file is smaller than expected.\n");
status = -1;
break;
}

else if (ferror(f)) {
printf("load_pifrom: An error occured while reading the ROM.\n");
status = -2;
break;
}
}

fclose(f);
return status;
}

// Creates and initializes a device.
struct cen64_device *device_create(const char *pifrom) {
struct cen64_device *device;

// Allocate memory.
if ((device = (struct cen64_device*) malloc(sizeof(*device))) == NULL)
return NULL;

// Initialize the PIF.
if (load_pifrom(pifrom, device->pifrom) < 0 ||
init_pif(&device->pif, &device->bus, device->pifrom)) {
printf("create_device: Failed to initialize the PIF.\n");

free(device);
return NULL;
}

// Initialize the bus.
if (bus_init(&device->bus)) {
printf("create_device: Failed to initialize the bus.\n");

free(device);
return NULL;
}

device->bus.pif = &device->pif;
device->bus.vr4300 = &device->vr4300;

// Initialize the VR4300.
if (vr4300_init(&device->vr4300, &device->bus)) {
printf("create_device: Failed to initialize the VR4300.\n");

free(device);
return NULL;
}

return device;
}

// Deallocates and cleans up a device.
void device_destroy(struct cen64_device *device) {
free(device);
}

// Kicks off threads and starts the device.
void device_run(struct cen64_device *device) {
unsigned i;

for (i = 0; i < 93750000; i++)
vr4300_cycle(&device->vr4300);
}

0 comments on commit 2f3aded

Please sign in to comment.