21 Commits

Author SHA1 Message Date
David Voswinkel
764c0dd2c1 o compiles and still crashes 2009-05-14 20:22:39 +02:00
David Voswinkel
a1763efe21 o mac compiles and stil crashed 2009-05-14 20:21:18 +02:00
David Voswinkel
b3d930b143 o cleanup mocs 2009-05-12 23:18:16 +02:00
David Voswinkel
3063b354e7 o mac compiles 2009-05-12 23:17:44 +02:00
David Voswinkel
571737d59b o add missing files 2009-05-12 22:24:35 +02:00
David Voswinkel
09198f5099 o add missing files 2009-05-12 22:20:41 +02:00
David Voswinkel
8e877d38d4 o switch to v46 2009-05-12 22:17:42 +02:00
David Voswinkel
7a878eab39 o compiles now for mac but crashes 2009-05-12 22:15:09 +02:00
David Voswinkel
091b82a7ef o add my bsnes branch 2009-05-12 20:05:00 +02:00
David Voswinkel
1c30d3db56 o remove old bsnes version 2009-05-12 19:44:23 +02:00
David Voswinkel
9cf6eae076 o add missing files
o add usbload
2009-05-12 19:01:03 +02:00
David Voswinkel
67a25941a7 o add kirby 2009-05-12 18:58:59 +02:00
David Voswinkel
aedc6dab5b o add gnususb as reference bootloader
o refactor boot loader  cpde
o
2009-05-06 23:55:56 +02:00
optixx
c40b9c32b6 o cleanup code
o add more states
o decouple read buffer size
2009-05-04 00:13:24 +02:00
optixx
59aad4c7a8 o done testing 2009-05-03 18:35:40 +02:00
optixx
af48032798 o add first working draft of usb version
o having bad sync problems only can use 4 bytes buffer, supper slow
2009-05-03 18:25:40 +02:00
optixx
d481bd5061 o cleanup 2009-05-02 13:19:58 +02:00
optixx
96c273fe89 o start usb uploadr avr 2009-05-02 11:35:13 +02:00
optixx
25c1f38aed o add vusb 2009-05-02 11:28:11 +02:00
optixx
0693dbc933 o add more test roms 2009-04-27 09:29:36 +02:00
optixx
500e6326c1 o add missing roms 2009-04-26 19:46:28 +02:00
530 changed files with 47538 additions and 11434 deletions

View File

@@ -1,18 +0,0 @@
--- !ditz.rubyforge.org,2008-03-06/issue
title: Test
desc: Test
type: :bugfix
component: snesram
release:
reporter: David <david@optixx.org>
status: :unstarted
disposition:
creation_time: 2009-04-20 18:13:29.104365 Z
references: []
id: 33e57a7c3ac89afc2e37880441fe0eeec05e2b3f
log_events:
- - 2009-04-20 18:13:33.543384 Z
- David <david@optixx.org>
- created
- nope

View File

@@ -182,7 +182,7 @@ AVRDUDE_PROGRAMMER = stk500v2
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = /dev/tty.PL2303-00001124
AVRDUDE_PORT =/dev/tty.PL2303-00001124
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex

View File

@@ -29,7 +29,7 @@ extern FILE uart_stdout;
#define RAM_REG PINA
#define CTRL_PORT PORTB
#define CTR_DIR DDRB
#define CTRL_DIR DDRB
#define LATCH_PORT PORTB
#define LATCH_DIR DDRB
@@ -42,10 +42,10 @@ extern FILE uart_stdout;
//#define FILENAME "sprite.raw" //ok
//#define FILENAME "ascii.smc" //ok
//#define FILENAME "rom.smc" //ok
//#define FILENAME "supert.smc"
//#define FILENAME "vortex.smc"
//#define FILENAME "mrdo.smc"
//#define FILENAME "spacei.smc"
//#define FILENAME "supert.smc" //ok
//#define FILENAME "vortex.smc" //failed
//#define FILENAME "mrdo.smc" //failed
//#define FILENAME "spacei.smc" //ok ntsc
//#define FILENAME "bank01.smc" //ok
//#define FILENAME "bank02.smc" //ok
//#define FILENAME "bank03.smc" //ok
@@ -56,9 +56,14 @@ extern FILE uart_stdout;
//#define FILENAME "banklo.smc" //ok
//#define FILENAME "bankhi.smc" //ok
//#define FILENAME "vram2.smc" //ok
//#define FILENAME "super02.smc"
#define FILENAME "crc.smc"
//#define FILENAME "banks.smc"
//#define FILENAME "super02.smc" //ok
//#define FILENAME "super01.smc"//ok
//#define FILENAME "crc.smc" //ok
//#define FILENAME "banks.smc" //ok
//#define FILENAME "hungry.smc" //ok
//#define FILENAME "arkanoid.smc"//ok
//#define FILENAME "eric.smc"
#define FILENAME "turrican.smc"
#define ROMSIZE 4
#define DUMPNAME "dump256.smc"
@@ -233,18 +238,28 @@ void sram_init(void){
RAM_DIR = 0x00;
RAM_PORT = 0x00;
CTR_DIR |= ((1<<R_WR) | (1<<R_RD));
CTRL_DIR |= ((1<<R_WR) | (1<<R_RD));
CTRL_PORT |= (1<<R_RD);
CTRL_PORT |= (1<<R_WR);
LED_PORT |= (1<<D_LED0);
}
void sram_snes_mode(void){
void sram_snes_mode01(void){
CTRL_PORT |= (1<<R_WR);
CTRL_PORT &= ~(1<<R_RD);
}
void sram_snes_mode02(void){
CTRL_DIR |= (1<<R_WR);
CTRL_PORT |= (1<<R_WR);
//CTRL_PORT &= ~(1<<R_RD);
CTRL_DIR &= ~(1<<R_RD);
CTRL_PORT &= ~(1<<R_RD);
}
void sram_clear(uint32_t addr, uint32_t len){
uint32_t i;
@@ -426,8 +441,17 @@ int main(void)
}
#endif
sram_snes_mode();
printf("\nEnter Snes mode\n");
#if 0
sram_snes_mode01();
printf("\nEnter Snes mode 02\n");
#endif
#if 0
sram_snes_mode02();
printf("\nEnter Snes mode 02\n");
#endif
printf("\nUpload done.\n");
while(1);
return 0 ;

168
poc/avr_usbload/Makefile Normal file
View File

@@ -0,0 +1,168 @@
# Name: Makefile
# Project: custom-class example
# Author: Christian Starkjohann
# Creation Date: 2008-04-07
# Tabsize: 4
# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
# License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
# This Revision: $Id: Makefile 692 2008-11-07 15:07:40Z cs $
DEVICE = atmega16
F_CPU = 16000000 # in Hz
FUSE_L = # see below for fuse values for particular devices
FUSE_H =
AVRDUDE = avrdude -c stk500v2 -p $(DEVICE) -P /dev/tty.PL2303-00002006
#AVRDUDE = avrdude -c stk500v2 -p $(DEVICE) -P /dev/tty.PL2303-00001424
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=0
#-std=gnu99
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o uart.o fifo.o sram.o crc.o debug.o
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)
##############################################################################
# Fuse values for particular devices
##############################################################################
# If your device is not listed here, go to
# http://palmavr.sourceforge.net/cgi-bin/fc.cgi
# and choose options for external crystal clock and no clock divider
#
################################## ATMega8 ##################################
# ATMega8 FUSE_L (Fuse low byte):
# 0x9f = 1 0 0 1 1 1 1 1
# ^ ^ \ / \--+--/
# | | | +------- CKSEL 3..0 (external >8M crystal)
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
# | +------------------ BODEN (BrownOut Detector enabled)
# +-------------------- BODLEVEL (2.7V)
# ATMega8 FUSE_H (Fuse high byte):
# 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000)
# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0
# | | | | | +-------- BOOTSZ1
# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase)
# | | | +-------------- CKOPT (full output swing)
# | | +---------------- SPIEN (allow serial programming)
# | +------------------ WDTON (WDT not always on)
# +-------------------- RSTDISBL (reset pin is enabled)
#
############################## ATMega48/88/168 ##############################
# ATMega*8 FUSE_L (Fuse low byte):
# 0xdf = 1 1 0 1 1 1 1 1
# ^ ^ \ / \--+--/
# | | | +------- CKSEL 3..0 (external >8M crystal)
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
# | +------------------ CKOUT (if 0: Clock output enabled)
# +-------------------- CKDIV8 (if 0: divide by 8)
# ATMega*8 FUSE_H (Fuse high byte):
# 0xde = 1 1 0 1 1 1 1 0
# ^ ^ ^ ^ ^ \-+-/
# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V)
# | | | | + --------- EESAVE (preserve EEPROM over chip erase)
# | | | +-------------- WDTON (if 0: watchdog always on)
# | | +---------------- SPIEN (allow serial programming)
# | +------------------ DWEN (debug wire enable)
# +-------------------- RSTDISBL (reset pin is enabled)
#
############################## ATTiny25/45/85 ###############################
# ATMega*5 FUSE_L (Fuse low byte):
# 0xef = 1 1 1 0 1 1 1 1
# ^ ^ \+/ \--+--/
# | | | +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz)
# | | +--------------- SUT 1..0 (BOD enabled, fast rising power)
# | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
# +-------------------- CKDIV8 (divide clock by 8 -> don't divide)
# ATMega*5 FUSE_H (Fuse high byte):
# 0xdd = 1 1 0 1 1 1 0 1
# ^ ^ ^ ^ ^ \-+-/
# | | | | | +------ BODLEVEL 2..0 (brownout trigger level -> 2.7V)
# | | | | +---------- EESAVE (preserve EEPROM on Chip Erase -> not preserved)
# | | | +-------------- WDTON (watchdog timer always on -> disable)
# | | +---------------- SPIEN (enable serial programming -> enabled)
# | +------------------ DWEN (debug wire enable)
# +-------------------- RSTDISBL (disable external reset -> enabled)
#
################################ ATTiny2313 #################################
# ATTiny2313 FUSE_L (Fuse low byte):
# 0xef = 1 1 1 0 1 1 1 1
# ^ ^ \+/ \--+--/
# | | | +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz)
# | | +--------------- SUT 1..0 (BOD enabled, fast rising power)
# | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
# +-------------------- CKDIV8 (divide clock by 8 -> don't divide)
# ATTiny2313 FUSE_H (Fuse high byte):
# 0xdb = 1 1 0 1 1 0 1 1
# ^ ^ ^ ^ \-+-/ ^
# | | | | | +---- RSTDISBL (disable external reset -> enabled)
# | | | | +-------- BODLEVEL 2..0 (brownout trigger level -> 2.7V)
# | | | +-------------- WDTON (watchdog timer always on -> disable)
# | | +---------------- SPIEN (enable serial programming -> enabled)
# | +------------------ EESAVE (preserve EEPROM on Chip Erase -> not preserved)
# +-------------------- DWEN (debug wire enable)
# symbolic targets:
help:
@echo "This Makefile has no default rule. Use one of the following:"
@echo "make hex ....... to build main.hex"
@echo "make program ... to flash fuses and firmware"
@echo "make fuse ...... to flash the fuses"
@echo "make flash ..... to flash the firmware (use this on metaboard)"
@echo "make clean ..... to delete objects and hex file"
all: hex
hex: main.hex
program: flash fuse
# rule for programming fuse bits:
fuse:
@[ "$(FUSE_H)" != "" -a "$(FUSE_L)" != "" ] || \
{ echo "*** Edit Makefile and choose values for FUSE_L and FUSE_H!"; exit 1; }
$(AVRDUDE) -U hfuse:w:$(FUSE_H):m -U lfuse:w:$(FUSE_L):m
# rule for uploading firmware:
flash: main.hex
$(AVRDUDE) -U flash:w:main.hex:i
# rule for deleting dependent files (those which can be built by Make):
clean:
rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s
# Generic rule for compiling C files:
.c.o:
$(COMPILE) -c $< -o $@
# Generic rule for assembling Assembler source files:
.S.o:
$(COMPILE) -x assembler-with-cpp -c $< -o $@
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.
# Generic rule for compiling C to assembler, used for debugging only.
.c.s:
$(COMPILE) -S $< -o $@
# file targets:
# Since we don't want to ship the driver multipe times, we copy it into this project:
usbdrv:
cp -r ../../../usbdrv .
main.elf: usbdrv $(OBJECTS) # usbdrv dependency only needed because we copy it
$(COMPILE) -o main.elf $(OBJECTS)
main.hex: main.elf
rm -f main.hex main.eep.hex
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avr-size main.hex
# debugging targets:
disasm: main.elf
avr-objdump -d main.elf
cpp:
$(COMPILE) -E main.c

35
poc/avr_usbload/checksize Normal file
View File

@@ -0,0 +1,35 @@
#!/bin/sh
# Name: checksize
# Project: PowerSwitch/AVR-USB
# Author: Christian Starkjohann
# Creation Date: 2004-12-29
# Tabsize: 4
# Copyright: (c) 2005 OBJECTIVE DEVELOPMENT Software GmbH.
# Revision: $Id: checksize 83 2006-01-05 22:20:53Z cs $
error=0
codelimit=16384 # default value
datalimit=992 # default value; leave 32 bytes for stack
if [ $# -gt 1 ]; then
codelimit="$2"
fi
if [ $# -gt 2 ]; then
datalimit="$3"
fi
set -- `avr-size -d "$1" | awk '/[0-9]/ {print $1 + $2, $2 + $3, $2}'`
if [ $1 -gt $codelimit ]; then
echo "*** code size $1 exceeds limit of $codelimit"
error=1
else
echo "ROM: $1 bytes (data=$3)"
fi
if [ $2 -gt $datalimit ]; then
echo "*** data size $2 exceeds limit of $datalimit"
error=1
else
echo "RAM: $2 bytes"
fi
exit $error

View File

@@ -0,0 +1,48 @@
# Name: Makefile
# Project: custom-class example
# Author: Christian Starkjohann
# Creation Date: 2008-04-06
# Tabsize: 4
# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
# License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
# This Revision: $Id: Makefile 692 2008-11-07 15:07:40Z cs $
# Concigure the following definitions according to your system.
# This Makefile has been tested on Mac OS X, Linux and Windows.
# Use the following 3 lines on Unix (uncomment the framework on Mac OS X):
USBFLAGS = `libusb-config --cflags`
USBLIBS = `libusb-config --libs`
EXE_SUFFIX =
# Use the following 3 lines on Windows and comment out the 3 above. You may
# have to change the include paths to where you installed libusb-win32
#USBFLAGS = -I/usr/local/include
#USBLIBS = -L/usr/local/lib -lusb
#EXE_SUFFIX = .exe
NAME = snesuploader
OBJECTS = opendevice.o $(NAME).o
CC = gcc
CFLAGS = $(CPPFLAGS) $(USBFLAGS) -O -g -Wall
LIBS = $(USBLIBS)
PROGRAM = $(NAME)$(EXE_SUFFIX)
all: $(PROGRAM)
.c.o:
$(CC) $(CFLAGS) -c $<
$(PROGRAM): $(OBJECTS)
$(CC) -o $(PROGRAM) $(OBJECTS) $(LIBS)
strip: $(PROGRAM)
strip $(PROGRAM)
clean:
rm -f *.o $(PROGRAM)

View File

@@ -0,0 +1,285 @@
/*
* Name: opendevice.c Project: V-USB host-side library Author: Christian
* Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c) 2008 by
* OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see License.txt),
* GNU GPL v3 or proprietary (CommercialLicense.txt) This Revision: $Id:
* opendevice.c 740 2009-04-13 18:23:31Z cs $
*/
/*
* General Description: The functions in this module can be used to find and
* open a device based on libusb or libusb-win32.
*/
#include <stdio.h>
#include "opendevice.h"
/*
* -------------------------------------------------------------------------
*/
#define MATCH_SUCCESS 1
#define MATCH_FAILED 0
#define MATCH_ABORT -1
/*
* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or
* MATCH_ABORT.
*/
static int _shellStyleMatch(char *text, char *p)
{
int last,
matched,
reverse;
for (; *p; text++, p++) {
if (*text == 0 && *p != '*')
return MATCH_ABORT;
switch (*p) {
case '\\':
/*
* Literal match with following character.
*/
p++;
/*
* FALLTHROUGH
*/
default:
if (*text != *p)
return MATCH_FAILED;
continue;
case '?':
/*
* Match anything.
*/
continue;
case '*':
while (*++p == '*')
/*
* Consecutive stars act just like one.
*/
continue;
if (*p == 0)
/*
* Trailing star matches everything.
*/
return MATCH_SUCCESS;
while (*text)
if ((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
return matched;
return MATCH_ABORT;
case '[':
reverse = p[1] == '^';
if (reverse) /* Inverted character class. */
p++;
matched = MATCH_FAILED;
if (p[1] == ']' || p[1] == '-')
if (*++p == *text)
matched = MATCH_SUCCESS;
for (last = *p; *++p && *p != ']'; last = *p)
if (*p == '-' && p[1] != ']' ? *text <= *++p
&& *text >= last : *text == *p)
matched = MATCH_SUCCESS;
if (matched == reverse)
return MATCH_FAILED;
continue;
}
}
return *text == 0;
}
/*
* public interface for shell style matching: returns 0 if fails, 1 if matches
*/
static int shellStyleMatch(char *text, char *pattern)
{
if (pattern == NULL) /* NULL pattern is synonymous to "*" */
return 1;
return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
}
/*
* -------------------------------------------------------------------------
*/
int usbGetStringAscii(usb_dev_handle * dev, int index, char *buf, int buflen)
{
char buffer[256];
int rval,
i;
if ((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use
* libusb
* version
* if
* it
* works
*/
return rval;
if ((rval =
usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) + index, 0x0409, buffer,
sizeof(buffer), 5000)) < 0)
return rval;
if (buffer[1] != USB_DT_STRING) {
*buf = 0;
return 0;
}
if ((unsigned char) buffer[0] < rval)
rval = (unsigned char) buffer[0];
rval /= 2;
/*
* lossy conversion to ISO Latin1:
*/
for (i = 1; i < rval; i++) {
if (i > buflen) /* destination buffer overflow */
break;
buf[i - 1] = buffer[2 * i];
if (buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
buf[i - 1] = '?';
}
buf[i - 1] = 0;
return i - 1;
}
/*
* -------------------------------------------------------------------------
*/
int usbOpenDevice(usb_dev_handle ** device, int vendorID,
char *vendorNamePattern, int productID,
char *productNamePattern, char *serialNamePattern,
FILE * printMatchingDevicesFp, FILE * warningsFp)
{
struct usb_bus *bus;
struct usb_device *dev;
usb_dev_handle *handle = NULL;
int errorCode = USBOPEN_ERR_NOTFOUND;
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) { /* iterate over
* all devices
* on all
* busses */
if ((vendorID == 0 || dev->descriptor.idVendor == vendorID)
&& (productID == 0 || dev->descriptor.idProduct == productID)) {
char vendor[256],
product[256],
serial[256];
int len;
handle = usb_open(dev); /* we need to open the device in order
* to query strings */
if (!handle) {
errorCode = USBOPEN_ERR_ACCESS;
if (warningsFp != NULL)
fprintf(warningsFp,
"Warning: cannot open VID=0x%04x PID=0x%04x: %s\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct, usb_strerror());
continue;
}
/*
* now check whether the names match:
*/
len = vendor[0] = 0;
if (dev->descriptor.iManufacturer > 0) {
len =
usbGetStringAscii(handle, dev->descriptor.iManufacturer,
vendor, sizeof(vendor));
}
if (len < 0) {
errorCode = USBOPEN_ERR_ACCESS;
if (warningsFp != NULL)
fprintf(warningsFp,
"Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct, usb_strerror());
} else {
errorCode = USBOPEN_ERR_NOTFOUND;
/*
* printf("seen device from vendor ->%s<-\n", vendor);
*/
if (shellStyleMatch(vendor, vendorNamePattern)) {
len = product[0] = 0;
if (dev->descriptor.iProduct > 0) {
len =
usbGetStringAscii(handle,
dev->descriptor.iProduct,
product, sizeof(product));
}
if (len < 0) {
errorCode = USBOPEN_ERR_ACCESS;
if (warningsFp != NULL)
fprintf(warningsFp,
"Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct,
usb_strerror());
} else {
errorCode = USBOPEN_ERR_NOTFOUND;
/*
* printf("seen product ->%s<-\n", product);
*/
if (shellStyleMatch(product, productNamePattern)) {
len = serial[0] = 0;
if (dev->descriptor.iSerialNumber > 0) {
len =
usbGetStringAscii(handle,
dev->descriptor.
iSerialNumber, serial,
sizeof(serial));
}
if (len < 0) {
errorCode = USBOPEN_ERR_ACCESS;
if (warningsFp != NULL)
fprintf(warningsFp,
"Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct,
usb_strerror());
}
if (shellStyleMatch(serial, serialNamePattern)) {
if (printMatchingDevicesFp != NULL) {
if (serial[0] == 0) {
fprintf(printMatchingDevicesFp,
"VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct,
vendor, product);
} else {
fprintf(printMatchingDevicesFp,
"VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct,
vendor, product, serial);
}
} else {
break;
}
}
}
}
}
}
usb_close(handle);
handle = NULL;
}
}
if (handle) /* we have found a deice */
break;
}
if (handle != NULL) {
errorCode = 0;
*device = handle;
}
if (printMatchingDevicesFp != NULL) /* never return an error for listing
* only */
errorCode = 0;
return errorCode;
}
/*
* -------------------------------------------------------------------------
*/

View File

@@ -1,11 +1,11 @@
/* Name: opendevice.h
* Project: AVR-USB host-side library
* Project: V-USB host-side library
* Author: Christian Starkjohann
* Creation Date: 2008-04-10
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: opendevice.h 692 2008-11-07 15:07:40Z cs $
* This Revision: $Id: opendevice.h 740 2009-04-13 18:23:31Z cs $
*/
/*

View File

@@ -0,0 +1,244 @@
/*
* Name: set-led.c Project: custom-class, a basic USB example Author:
* Christian Starkjohann Creation Date: 2008-04-10 Tabsize: 4 Copyright: (c)
* 2008 by OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see
* License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) This
* Revision: $Id: set-led.c 692 2008-11-07 15:07:40Z cs $
*/
/*
* General Description: This is the host-side driver for the custom-class
* example device. It searches the USB for the LEDControl device and sends the
* requests understood by this device. This program must be linked with libusb
* on Unix and libusb-win32 on Windows. See http://libusb.sourceforge.net/ or
* http://libusb-win32.sourceforge.net/ respectively.
*/
#define READ_BUFFER_SIZE 1024
#define SEND_BUFFER_SIZE 128
#define BUFFER_CRC (1024 * 32)
#define BANK_SIZE (1<<15)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <usb.h> /* this is libusb */
#include "opendevice.h" /* common code moved to separate module */
#include "../requests.h" /* custom request numbers */
#include "../usbconfig.h" /* device's VID/PID and names */
void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet)
{
uint16_t i,
j;
uint16_t sum = 0;
uint8_t clear = 0;
for (i = 0; i < len; i += 16) {
sum = 0;
for (j = 0; j < 16; j++) {
sum += packet[i + j];
}
if (!sum) {
clear = 1;
continue;
}
if (clear) {
printf("*\n");
clear = 0;
}
printf("%08x:", addr + i);
for (j = 0; j < 16; j++) {
printf(" %02x", packet[i + j]);
}
printf(" |");
for (j = 0; j < 16; j++) {
if (packet[i + j] >= 33 && packet[i + j] <= 126)
printf("%c", packet[i + j]);
else
printf(".");
}
printf("|\n");
}
}
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
{
int i;
crc = crc ^ ((uint16_t) data << 8);
for (i = 0; i < 8; i++) {
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
return crc;
}
uint16_t do_crc(uint8_t * data, uint16_t size)
{
uint16_t crc = 0;
uint16_t i;
for (i = 0; i < size; i++) {
crc = crc_xmodem_update(crc, data[i]);
}
return crc;
}
uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size)
{
uint16_t i;
for (i = 0; i < size; i++)
crc = crc_xmodem_update(crc, data[i]);
return crc;
}
static void usage(char *name)
{
fprintf(stderr, "usage:\n");
fprintf(stderr, " %s upload filename.. upload\n", name);
}
int main(int argc, char **argv)
{
usb_dev_handle *handle = NULL;
const unsigned char rawVid[2] = { USB_CFG_VENDOR_ID }, rawPid[2] = {
USB_CFG_DEVICE_ID};
char vendor[] = { USB_CFG_VENDOR_NAME, 0 }, product[] = {
USB_CFG_DEVICE_NAME, 0};
int cnt,
vid,
pid;
int cnt_crc = 0;
uint8_t *read_buffer;
uint8_t *crc_buffer;
uint32_t addr = 0;
uint16_t addr_lo = 0;
uint16_t addr_hi = 0;
uint16_t step = 0;
uint16_t crc = 0;
uint8_t bank = 0;
FILE *fp;
usb_init();
if (argc < 2) { /* we need at least one argument */
usage(argv[0]);
exit(1);
}
/*
* compute VID/PID from usbconfig.h so that there is a central source
* of information
*/
vid = rawVid[1] * 256 + rawVid[0];
pid = rawPid[1] * 256 + rawPid[0];
/*
* The following function is in opendevice.c:
*/
if (usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) !=
0) {
fprintf(stderr,
"Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n",
product, vid, pid);
exit(1);
}
printf("Open USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid,
pid);
if (strcasecmp(argv[1], "upload") == 0) {
if (argc < 3) { /* we need at least one argument */
usage(argv[0]);
exit(1);
}
fp = fopen(argv[2], "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open file %s ", argv[2]);
exit(1);
}
read_buffer = (unsigned char *) malloc(READ_BUFFER_SIZE);
crc_buffer = (unsigned char *) malloc(BUFFER_CRC);
memset(crc_buffer, 0, BUFFER_CRC);
addr = 0x000000;
usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT,
USB_UPLOAD_INIT, 0, 0, NULL, 0, 5000);
while ((cnt = fread(read_buffer, READ_BUFFER_SIZE, 1, fp)) > 0) {
for (step = 0; step < READ_BUFFER_SIZE; step += SEND_BUFFER_SIZE) {
addr_lo = addr & 0xffff;
addr_hi = (addr >> 16) & 0xff;
usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_UPLOAD_ADDR, addr_hi,
addr_lo, (char *) read_buffer + step,
SEND_BUFFER_SIZE, 5000);
#if 0
dump_packet(addr, SEND_BUFFER_SIZE, read_buffer + step);
#endif
addr += SEND_BUFFER_SIZE;
}
memcpy(crc_buffer + cnt_crc, read_buffer, READ_BUFFER_SIZE);
cnt_crc += READ_BUFFER_SIZE;
if (cnt_crc >= BANK_SIZE) {
crc = do_crc(crc_buffer, BANK_SIZE);
printf
("Addr: 0x%06x Bank: 0x%02x HiAddr: 0x%02x LoAddr: 0x%04x Crc: 0x%04x\n",
addr, bank, addr_hi, addr_lo, crc);
memset(crc_buffer, 0, BUFFER_CRC);
bank++;
cnt_crc = 0;
}
}
cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_CRC, addr_hi, addr_lo, NULL,
0, 5000);
if (cnt < 1) {
if (cnt < 0) {
fprintf(stderr, "USB error: %s\n", usb_strerror());
} else {
fprintf(stderr, "only %d bytes received.\n", cnt);
}
}
} else if (strcasecmp(argv[1], "crc") == 0) {
/*
* if(argc < 2){ usage(argv[0]); exit(1); }
*/
addr = 0x000000;
addr_lo = addr & 0xffff;
addr_hi = (addr >> 16) & 0xff;
printf("Request CRC for Addr: 0x%06x\n", addr);
cnt = usb_control_msg(handle,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_ENDPOINT_OUT, USB_CRC_ADDR, addr_hi, addr_lo,
NULL, (1 << 15) / 4, 5000);
if (cnt < 1) {
if (cnt < 0) {
fprintf(stderr, "USB error: %s\n", usb_strerror());
} else {
fprintf(stderr, "only %d bytes received.\n", cnt);
}
}
} else {
usage(argv[0]);
exit(1);
}
usb_close(handle);
return 0;
}

41
poc/avr_usbload/crc.c Normal file
View File

@@ -0,0 +1,41 @@
#include <stdlib.h>
#include <stdint.h>
#include "crc.h"
#include "uart.h"
extern FILE uart_stdout;
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
{
int i;
crc = crc ^ ((uint16_t) data << 8);
for (i = 0; i < 8; i++) {
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
return crc;
}
uint16_t do_crc(uint8_t * data, uint16_t size)
{
uint16_t crc = 0;
uint16_t i;
for (i = 0; i < size; i++) {
crc = crc_xmodem_update(crc, data[i]);
// printf("%x : %x\n",crc,data[i]);
}
return crc;
}
uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size)
{
uint16_t i;
for (i = 0; i < size; i++)
crc = crc_xmodem_update(crc, data[i]);
return crc;
}

7
poc/avr_usbload/crc.h Normal file
View File

@@ -0,0 +1,7 @@
#include <stdlib.h>
#include <stdint.h>
uint16_t crc_xmodem_update (uint16_t crc, uint8_t data);
uint16_t do_crc(uint8_t * data,uint16_t size);
uint16_t do_crc_update(uint16_t crc,uint8_t * data,uint16_t size);

44
poc/avr_usbload/debug.c Normal file
View File

@@ -0,0 +1,44 @@
#include <stdlib.h>
#include <stdint.h>
#include "debug.h"
#include "uart.h"
extern FILE uart_stdout;
void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet)
{
uint16_t i,
j;
uint16_t sum = 0;
uint8_t clear = 0;
for (i = 0; i < len; i += 16) {
sum = 0;
for (j = 0; j < 16; j++) {
sum += packet[i + j];
}
if (!sum) {
clear = 1;
continue;
}
if (clear) {
printf("*\n");
clear = 0;
}
printf("%08lx:", addr + i);
for (j = 0; j < 16; j++) {
printf(" %02x", packet[i + j]);
}
printf(" |");
for (j = 0; j < 16; j++) {
if (packet[i + j] >= 33 && packet[i + j] <= 126)
printf("%c", packet[i + j]);
else
printf(".");
}
printf("|\n");
}
}

5
poc/avr_usbload/debug.h Normal file
View File

@@ -0,0 +1,5 @@
#include <stdlib.h>
#include <stdint.h>
void dump_packet(uint32_t addr,uint32_t len,uint8_t *packet);

28
poc/avr_usbload/fifo.c Normal file
View File

@@ -0,0 +1,28 @@
#include "fifo.h"
void fifo_init(fifo_t * f, uint8_t * buffer, const uint8_t size)
{
f->count = 0;
f->pread = f->pwrite = buffer;
f->read2end = f->write2end = f->size = size;
}
uint8_t fifo_put(fifo_t * f, const uint8_t data)
{
return _inline_fifo_put(f, data);
}
uint8_t fifo_get_wait(fifo_t * f)
{
while (!f->count);
return _inline_fifo_get(f);
}
int fifo_get_nowait(fifo_t * f)
{
if (!f->count)
return -1;
return (int) _inline_fifo_get(f);
}

69
poc/avr_usbload/fifo.h Normal file
View File

@@ -0,0 +1,69 @@
#ifndef _FIFO_H_
#define _FIFO_H_
#include <avr/io.h>
#include <avr/interrupt.h>
typedef struct {
uint8_t volatile count; // # Zeichen im Puffer
uint8_t size; // Puffer-Größe
uint8_t *pread; // Lesezeiger
uint8_t *pwrite; // Schreibzeiger
uint8_t read2end, write2end; // # Zeichen bis zum Überlauf Lese-/Schreibzeiger
} fifo_t;
extern void fifo_init(fifo_t *, uint8_t * buf, const uint8_t size);
extern uint8_t fifo_put(fifo_t *, const uint8_t data);
extern uint8_t fifo_get_wait(fifo_t *);
extern int fifo_get_nowait(fifo_t *);
static inline uint8_t _inline_fifo_put(fifo_t * f, const uint8_t data)
{
if (f->count >= f->size)
return 0;
uint8_t *pwrite = f->pwrite;
*(pwrite++) = data;
uint8_t write2end = f->write2end;
if (--write2end == 0) {
write2end = f->size;
pwrite -= write2end;
}
f->write2end = write2end;
f->pwrite = pwrite;
uint8_t sreg = SREG;
cli();
f->count++;
SREG = sreg;
return 1;
}
static inline uint8_t _inline_fifo_get(fifo_t * f)
{
uint8_t *pread = f->pread;
uint8_t data = *(pread++);
uint8_t read2end = f->read2end;
if (--read2end == 0) {
read2end = f->size;
pread -= read2end;
}
f->pread = pread;
f->read2end = read2end;
uint8_t sreg = SREG;
cli();
f->count--;
SREG = sreg;
return data;
}
#endif /* _FIFO_H_ */

213
poc/avr_usbload/main.c Normal file
View File

@@ -0,0 +1,213 @@
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h> /* for sei() */
#include <util/delay.h> /* for _delay_ms() */
#include <stdlib.h>
#include <avr/pgmspace.h> /* required by usbdrv.h */
#include "usbdrv.h"
#include "oddebug.h" /* This is also an example for using debug
* macros */
#include "requests.h" /* The custom request numbers we use */
#include "uart.h"
#include "sram.h"
#include "debug.h"
#include "crc.h"
#define REQ_IDLE 0
#define REQ_UPLOAD 1
#define RES_CRC 2
#define BUFFER_SIZE 256
extern FILE uart_stdout;
uint8_t read_buffer[BUFFER_SIZE];
uint32_t req_addr = 0;
uint32_t req_size;
uint8_t req_bank;
uint32_t req_bank_size;
uint8_t req_state = REQ_IDLE;
uint8_t rx_remaining = 0;
uint8_t tx_remaining = 0;
uint16_t sync_errors = 0;
uint8_t tx_buffer[32];
uint8_t data_buffer[4];
uint32_t addr;
void crc_check_memory(uint32_t top_addr)
{
uint16_t crc = 0;
uint32_t addr;
req_bank = 0;
for (addr = 0x000000; addr < top_addr; addr += BUFFER_SIZE) {
sram_read_buffer(addr, read_buffer, BUFFER_SIZE);
crc = do_crc_update(crc, read_buffer, BUFFER_SIZE);
if (addr && addr % 32768 == 0) {
printf("crc_check_memory: req_bank: 0x%x Addr: 0x%lx CRC: %x\n",
req_bank, addr, crc);
req_bank++;
crc = 0;
}
}
}
void crc_check_memory_
range(uint32_t start_addr, uint32_t size)
{
uint16_t crc = 0;
uint32_t addr;
req_bank = 0;
for (addr = start_addr; addr < start_addr + size; addr += BUFFER_SIZE) {
sram_read_buffer(addr, read_buffer, BUFFER_SIZE);
crc = do_crc_update(crc, read_buffer, BUFFER_SIZE);
}
tx_buffer[0] = crc & 0xff;
tx_buffer[1] = (crc >> 8) & 0xff;
printf("crc_check_memory_range: Addr: 0x%lx CRC: %x\n", addr, crc);
}
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *) data;
uint8_t ret_len = 0;
if (rq->bRequest == USB_UPLOAD_INIT) {
req_bank = 0;
rx_remaining = 0;
req_bank_size = 1 << rq->wValue.word;
sync_errors = 0;
printf("USB_UPLOAD_INIT: bank size %li\n", req_bank_size);
} else if (rq->bRequest == USB_UPLOAD_ADDR) { /* echo -- used for
* reliability tests */
req_state = REQ_UPLOAD;
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
if (rx_remaining) {
sync_errors++;
printf
("USB_UPLOAD_ADDR: Out of sync Addr=0x%lx remain=%i packet=%i sync_error=%i\n",
req_addr, rx_remaining, rq->wLength.word, sync_errors);
ret_len = 0;
}
rx_remaining = rq->wLength.word;
ret_len = 0xff;
if (req_addr && req_addr % req_bank_size == 0) {
printf("USB_UPLOAD_ADDR: req_bank: 0x%x Addr: 0x%08lx \n",
req_bank, req_addr);
req_bank++;
}
ret_len = 0xff;
} else if (rq->bRequest == USB_DOWNLOAD_INIT) {
printf("USB_DOWNLOAD_INIT\n");
} else if (rq->bRequest == USB_DOWNLOAD_ADDR) {
printf("USB_DOWNLOAD_ADDR\n");
} else if (rq->bRequest == USB_CRC) {
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
printf("USB_CRC: Addr 0x%lx \n", req_addr);
cli();
crc_check_memory(req_addr);
sei();
} else if (rq->bRequest == USB_CRC_ADDR) {
req_addr = rq->wValue.word;
req_addr = req_addr << 16;
req_addr = req_addr | rq->wIndex.word;
printf("USB_CRC_ADDR: Addr: 0x%lx Size: %i\n", req_addr,
rq->wLength.word);
req_size = rq->wLength.word;
req_size = req_size << 2;
tx_remaining = 2;
printf("USB_CRC_ADDR: Addr: 0x%lx Size: %li\n", req_addr, req_size);
cli();
// crc_check_memory_range(req_addr,req_size);
sei();
ret_len = 2;
}
usbMsgPtr = data_buffer;
return ret_len; /* default for not implemented requests: return
* no data back to host */
}
uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
{
if (len > rx_remaining) {
printf("usbFunctionWrite more data than expected remain: %i len: %i\n",
rx_remaining, len);
len = rx_remaining;
}
if (req_state == REQ_UPLOAD) {
rx_remaining -= len;
#if 1
printf("usbFunctionWrite addr: 0x%08lx len: %i rx_remaining=%i\n",
req_addr, len, rx_remaining);
#endif
cli();
sram_copy(req_addr, data, len);
sei();
req_addr += len;
}
return len;
}
uint8_t usbFunctionRead(uint8_t * data, uint8_t len)
{
uint8_t i;
if (len > tx_remaining)
len = tx_remaining;
tx_remaining -= len;
#if 1
printf("usbFunctionRead len=%i tx_remaining=%i \n", len, tx_remaining);
#endif
for (i = 0; i < len; i++) {
*data = tx_buffer[len];
data++;
}
return len;
}
/*
* -------------------------------------------------------------------------
*/
int main(void)
{
uint8_t i;
wdt_enable(WDTO_1S);
uart_init();
stdout = &uart_stdout;
sram_init();
printf("SRAM Init\n");
spi_init();
printf("SPI Init\n");
usbInit();
printf("USB Init\n");
usbDeviceDisconnect(); /* enforce re-enumeration, do this while
* interrupts are disabled! */
printf("USB disconnect\n");
i = 10;
while (--i) { /* fake USB disconnect for > 250 ms */
wdt_reset();
_delay_ms(1);
}
usbDeviceConnect();
printf("USB connect\n");
sei();
printf("USB poll\n");
for (;;) { /* main event loop */
wdt_reset();
usbPoll();
}
return 0;
}
/*
* -------------------------------------------------------------------------
*/

View File

@@ -0,0 +1,26 @@
/* Name: requests.h
* Project: custom-class, a basic USB example
* Author: Christian Starkjohann
* Creation Date: 2008-04-09
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: requests.h 692 2008-11-07 15:07:40Z cs $
*/
/* This header is shared between the firmware and the host software. It
* defines the USB request numbers (and optionally data types) used to
* communicate between the host and the device.
*/
#ifndef __REQUESTS_H_INCLUDED__
#define __REQUESTS_H_INCLUDED__
#define USB_UPLOAD_INIT 0
#define USB_UPLOAD_ADDR 1
#define USB_DOWNLOAD_INIT 2
#define USB_DOWNLOAD_ADDR 3
#define USB_CRC 4
#define USB_CRC_ADDR 5
#endif /* __REQUESTS_H_INCLUDED__ */

172
poc/avr_usbload/sram.c Normal file
View File

@@ -0,0 +1,172 @@
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include "sram.h"
#include "uart.h"
#include "debug.h"
void spi_init(void)
{
/*
* Set MOSI and SCK output, all others input
*/
SPI_DIR |= ((1 << S_MOSI) | (1 << S_SCK) | (1 << S_LATCH));
SPI_DIR &= ~(1 << S_MISO);
SPI_PORT |= (1 << S_MISO);
/*
* Enable SPI, Master
*/
SPCR = ((1 << SPE) | (1 << MSTR));
}
void spi_master_transmit(unsigned char cData)
{
/*
* Start transmission
*/
SPDR = cData;
/*
* Wait for transmission complete
*/
while (!(SPSR & (1 << SPIF)));
}
void sram_set_addr(uint32_t addr)
{
spi_master_transmit((uint8_t) (addr >> 16));
spi_master_transmit((uint8_t) (addr >> 8));
spi_master_transmit((uint8_t) (addr >> 0));
LATCH_PORT |= (1 << S_LATCH);
LATCH_PORT &= ~(1 << S_LATCH);
}
uint8_t sram_read(uint32_t addr)
{
uint8_t byte;
RAM_DIR = 0x00;
RAM_PORT = 0xff;
CTRL_PORT |= (1 << R_RD);
CTRL_PORT |= (1 << R_WR);
spi_master_transmit((uint8_t) (addr >> 16));
spi_master_transmit((uint8_t) (addr >> 8));
spi_master_transmit((uint8_t) (addr >> 0));
LATCH_PORT |= (1 << S_LATCH);
LATCH_PORT &= ~(1 << S_LATCH);
CTRL_PORT &= ~(1 << R_RD);
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("nop");
byte = RAM_REG;
CTRL_PORT |= (1 << R_RD);
RAM_DIR = 0x00;
RAM_PORT = 0x00;
return byte;
}
void sram_write(uint32_t addr, uint8_t data)
{
RAM_DIR = 0xff;
CTRL_PORT |= (1 << R_RD);
CTRL_PORT |= (1 << R_WR);
spi_master_transmit((uint8_t) (addr >> 16));
spi_master_transmit((uint8_t) (addr >> 8));
spi_master_transmit((uint8_t) (addr >> 0));
LATCH_PORT |= (1 << S_LATCH);
LATCH_PORT &= ~(1 << S_LATCH);
CTRL_PORT &= ~(1 << R_WR);
RAM_PORT = data;
CTRL_PORT |= (1 << R_WR);
RAM_DIR = 0x00;
RAM_PORT = 0x00;
}
void sram_init(void)
{
RAM_DIR = 0x00;
RAM_PORT = 0x00;
CTRL_DIR |= ((1 << R_WR) | (1 << R_RD));
CTRL_PORT |= (1 << R_RD);
CTRL_PORT |= (1 << R_WR);
LED_PORT |= (1 << D_LED0);
}
void sram_snes_mode01(void)
{
CTRL_PORT |= (1 << R_WR);
CTRL_PORT &= ~(1 << R_RD);
}
void sram_snes_mode02(void)
{
CTRL_DIR |= (1 << R_WR);
CTRL_PORT |= (1 << R_WR);
// CTRL_PORT &= ~(1<<R_RD);
CTRL_DIR &= ~(1 << R_RD);
CTRL_PORT &= ~(1 << R_RD);
}
void sram_clear(uint32_t addr, uint32_t len)
{
uint32_t i;
for (i = addr; i < (addr + len); i++) {
if (0 == i % 0xfff)
printf("sram_clear %lx\n\r", i);
sram_write(i, 0x00);
}
}
void sram_copy(uint32_t addr, uint8_t * src, uint32_t len)
{
uint32_t i;
uint8_t *ptr = src;
for (i = addr; i < (addr + len); i++)
sram_write(i, *ptr++);
}
void sram_read_buffer(uint32_t addr, uint8_t * dst, uint32_t len)
{
uint32_t i;
uint8_t *ptr = dst;
for (i = addr; i < (addr + len); i++) {
*ptr = sram_read(i);
ptr++;
}
}
uint8_t sram_check(uint8_t * buffer, uint32_t len)
{
uint16_t cnt;
for (cnt = 0; cnt < len; cnt++)
if (buffer[cnt])
return 1;
return 0;
}

51
poc/avr_usbload/sram.h Normal file
View File

@@ -0,0 +1,51 @@
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
//SREG defines
#define S_MOSI PB5
#define S_MISO PB6
#define S_SCK PB7
#define S_LATCH PB4
//DEBUG defines
#define D_LED0 PD6
//SRAM defines
#define R_WR PB1
#define R_RD PB0
#define RAM_PORT PORTA
#define RAM_DIR DDRA
#define RAM_REG PINA
#define CTRL_PORT PORTB
#define CTRL_DIR DDRB
#define LATCH_PORT PORTB
#define LATCH_DIR DDRB
#define SPI_PORT PORTB
#define SPI_DIR DDRB
#define LED_PORT PORTD
#define LED_DIR DDRD
#define ROMSIZE 4
#define BLOCKS (ROMSIZE << 8)
#define MEMSIZE 0x80000
void spi_init(void);
void spi_master_transmit(unsigned char cData);
void sram_set_addr(uint32_t addr);
uint8_t sram_read(uint32_t addr);
void sram_write(uint32_t addr, uint8_t data);
void sram_init(void);
void sram_snes_mode01(void);
void sram_snes_mode02(void);
void sram_clear(uint32_t addr, uint32_t len);
void sram_copy(uint32_t addr,uint8_t *src, uint32_t len);
void sram_read_buffer(uint32_t addr,uint8_t *dst, uint32_t len);
uint8_t sram_check(uint8_t *buffer, uint32_t len);

77
poc/avr_usbload/uart.c Normal file
View File

@@ -0,0 +1,77 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "uart.h"
#include "fifo.h"
volatile struct {
uint8_t tmr_int:1;
uint8_t adc_int:1;
uint8_t rx_int:1;
} intflags;
/*
* * Last character read from the UART.
*
*/
volatile char rxbuff;
FILE uart_stdout = FDEV_SETUP_STREAM(uart_stream, NULL, _FDEV_SETUP_WRITE);
void uart_init(void)
{
UCSRA = _BV(U2X); /* improves baud rate error @ F_CPU = 1 MHz */
UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE); /* tx/rx enable, rx complete
* intr */
UBRRL = (F_CPU / (8 * 115200UL)) - 1; /* 9600 Bd */
}
ISR(USART_RXC_vect)
{
uint8_t c;
c = UDR;
if (bit_is_clear(UCSRA, FE)) {
rxbuff = c;
intflags.rx_int = 1;
}
}
void uart_putc(uint8_t c)
{
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
}
void uart_puts(const char *s)
{
do {
uart_putc(*s);
}
while (*s++);
}
void uart_puts_P(PGM_P s)
{
while (1) {
unsigned char c = pgm_read_byte(s);
s++;
if ('\0' == c)
break;
uart_putc(c);
}
}
static int uart_stream(char c, FILE * stream)
{
if (c == '\n')
uart_putc('\r');
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}

18
poc/avr_usbload/uart.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef _UART_H_
#define _UART_H_
#define CR "\r\n"
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdio.h>
void uart_init(void);
void uart_putc(const uint8_t);
void uart_puts(const char *s);
void uart_puts_P(PGM_P s);
static int uart_stream(char c, FILE *stream);
#endif /* _UART_H_ */

351
poc/avr_usbload/usbconfig.h Normal file
View File

@@ -0,0 +1,351 @@
/* Name: usbconfig.h
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2005-04-01
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
*/
#ifndef __usbconfig_h_included__
#define __usbconfig_h_included__
/*
General Description:
This file is an example configuration (with inline documentation) for the USB
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
other hardware interrupt, as long as it is the highest level interrupt, see
section at the end of this file).
*/
/* ---------------------------- Hardware Config ---------------------------- */
#define USB_CFG_IOPORTNAME D
/* This is the port where the USB bus is connected. When you configure it to
* "B", the registers PORTB, PINB and DDRB will be used.
*/
#define USB_CFG_DMINUS_BIT 4
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
* This may be any bit in the port.
*/
#define USB_CFG_DPLUS_BIT 2
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
* This may be any bit in the port. Please note that D+ must also be connected
* to interrupt pin INT0! [You can also use other interrupts, see section
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
* markers every millisecond.]
*/
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
* 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no
* crystal, they tolerate +/- 1% deviation from the nominal frequency. All
* other rates require a precision of 2000 ppm and thus a crystal!
* Default if not specified: 12 MHz
*/
#define USB_CFG_CHECK_CRC 0
/* Define this to 1 if you want that the driver checks integrity of incoming
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
* currently only available for 18 MHz crystal clock. You must choose
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
*/
/* ----------------------- Optional Hardware Config ------------------------ */
#define USB_CFG_PULLUP_IOPORTNAME D
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
* V+, you can connect and disconnect the device from firmware by calling
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
* This constant defines the port on which the pullup resistor is connected.
*/
#define USB_CFG_PULLUP_BIT 6
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
* above) where the 1.5k pullup resistor is connected. See description
* above for details.
*/
/* --------------------------- Functional Range ---------------------------- */
#define USB_CFG_HAVE_INTRIN_ENDPOINT 0
/* Define this to 1 if you want to compile a version with two endpoints: The
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
* number).
*/
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
/* Define this to 1 if you want to compile a version with three endpoints: The
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
* configured below) and a catch-all default interrupt-in endpoint as above.
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
*/
#define USB_CFG_EP3_NUMBER 3
/* If the so-called endpoint 3 is used, it can now be configured to any other
* endpoint number (except 0) with this macro. Default if undefined is 3.
*/
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
/* The above macro defines the startup condition for data toggling on the
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
* Since the token is toggled BEFORE sending any data, the first packet is
* sent with the oposite value of this configuration!
*/
#define USB_CFG_IMPLEMENT_HALT 0
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
* it is required by the standard. We have made it a config option because it
* bloats the code considerably.
*/
#define USB_CFG_SUPPRESS_INTR_CODE 1
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
* want to send any data over them. If this macro is defined to 1, functions
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
* you need the interrupt-in endpoints in order to comply to an interface
* (e.g. HID), but never want to send any data. This option saves a couple
* of bytes in flash memory and the transmit buffers in RAM.
*/
#define USB_CFG_INTR_POLL_INTERVAL 10
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
* interval. The value is in milliseconds and must not be less than 10 ms for
* low speed devices.
*/
#define USB_CFG_IS_SELF_POWERED 0
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
* device is powered from the USB bus.
*/
#define USB_CFG_MAX_BUS_POWER 40
/* Set this variable to the maximum USB bus power consumption of your device.
* The value is in milliamperes. [It will be divided by two since USB
* communicates power requirements in units of 2 mA.]
*/
#define USB_CFG_IMPLEMENT_FN_WRITE 1
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
* transfers. Set it to 0 if you don't need it and want to save a couple of
* bytes.
*/
#define USB_CFG_IMPLEMENT_FN_READ 0
/* Set this to 1 if you need to send control replies which are generated
* "on the fly" when usbFunctionRead() is called. If you only want to send
* data from a static buffer, set it to 0 and return the data from
* usbFunctionSetup(). This saves a couple of bytes.
*/
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
* You must implement the function usbFunctionWriteOut() which receives all
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
* can be found in 'usbRxToken'.
*/
#define USB_CFG_HAVE_FLOWCONTROL 0
/* Define this to 1 if you want flowcontrol over USB data. See the definition
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
* usbdrv.h.
*/
#define USB_CFG_LONG_TRANSFERS 0
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
* in a single control-in or control-out transfer. Note that the capability
* for long transfers increases the driver size.
*/
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
/* This macro is a hook if you want to do unconventional things. If it is
* defined, it's inserted at the beginning of received message processing.
* If you eat the received message and don't want default processing to
* proceed, do a return after doing your things. One possible application
* (besides debugging) is to flash a status LED on each packet.
*/
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
/* This macro is a hook if you need to know when an USB RESET occurs. It has
* one parameter which distinguishes between the start of RESET state and its
* end.
*/
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
* received.
*/
#define USB_COUNT_SOF 0
/* define this macro to 1 if you need the global variable "usbSofCount" which
* counts SOF packets. This feature requires that the hardware interrupt is
* connected to D- instead of D+.
*/
/* #ifdef __ASSEMBLER__
* macro myAssemblerMacro
* in YL, TCNT0
* sts timer0Snapshot, YL
* endm
* #endif
* #define USB_SOF_HOOK myAssemblerMacro
* This macro (if defined) is executed in the assembler module when a
* Start Of Frame condition is detected. It is recommended to define it to
* the name of an assembler macro which is defined here as well so that more
* than one assembler instruction can be used. The macro may use the register
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
* immediately after an SOF pulse may be lost and must be retried by the host.
* What can you do with this hook? Since the SOF signal occurs exactly every
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
* designs running on the internal RC oscillator.
* Please note that Start Of Frame detection works only if D- is wired to the
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
*/
#define USB_CFG_CHECK_DATA_TOGGLING 0
/* define this macro to 1 if you want to filter out duplicate data packets
* sent by the host. Duplicates occur only as a consequence of communication
* errors, when the host does not receive an ACK. Please note that you need to
* implement the filtering yourself in usbFunctionWriteOut() and
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
* for each control- and out-endpoint to check for duplicate packets.
*/
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
*/
/* -------------------------- Device Description --------------------------- */
#define USB_CFG_VENDOR_ID 0xc0, 0x16
/* USB vendor ID for the device, low byte first. If you have registered your
* own Vendor ID, define it here. Otherwise you use one of obdev's free shared
* VID/PID pairs. Be sure to read USBID-License.txt for rules!
*/
#define USB_CFG_DEVICE_ID 0xdc, 0x05
/* This is the ID of the product, low byte first. It is interpreted in the
* scope of the vendor ID. If you have registered your own VID with usb.org
* or if you have licensed a PID from somebody else, define it here. Otherwise
* you use obdev's free shared VID/PID pair. Be sure to read the rules in
* USBID-License.txt!
*/
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
/* Version number of the device: Minor number first, then major number.
*/
#define USB_CFG_VENDOR_NAME 'o', 'p', 't', 'i', 'x', 'x', '.', 'o', 'r', 'g'
#define USB_CFG_VENDOR_NAME_LEN 10
/* These two values define the vendor name returned by the USB device. The name
* must be given as a list of characters under single quotes. The characters
* are interpreted as Unicode (UTF-16) entities.
* If you don't want a vendor name string, undefine these macros.
* ALWAYS define a vendor name containing your Internet domain name if you use
* obdev's free shared VID/PID pair. See the file USBID-License.txt for
* details.
*/
#define USB_CFG_DEVICE_NAME 'S', 'N', 'E', 'S', 'R', 'A', 'M'
#define USB_CFG_DEVICE_NAME_LEN 7
/* Same as above for the device name. If you don't want a device name, undefine
* the macros. See the file USBID-License.txt before you assign a name if you
* use a shared VID/PID.
*/
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
/* Same as above for the serial number. If you don't want a serial number,
* undefine the macros.
* It may be useful to provide the serial number through other means than at
* compile time. See the section about descriptor properties below for how
* to fine tune control over USB descriptors such as the string descriptor
* for the serial number.
*/
#define USB_CFG_DEVICE_CLASS 0xff /* set to 0 if deferred to interface */
#define USB_CFG_DEVICE_SUBCLASS 0
/* See USB specification if you want to conform to an existing device class.
* Class 0xff is "vendor specific".
*/
#define USB_CFG_INTERFACE_CLASS 0 /* define class here if not at device level */
#define USB_CFG_INTERFACE_SUBCLASS 0
#define USB_CFG_INTERFACE_PROTOCOL 0
/* See USB specification if you want to conform to an existing device class or
* protocol. The following classes must be set at interface level:
* HID class is 3, no subclass and protocol required (but may be useful!)
* CDC class is 2, use subclass 2 and protocol 1 for ACM
*/
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0
/* Define this to the length of the HID report descriptor, if you implement
* an HID device. Otherwise don't define it or define it to 0.
* If you use this define, you must add a PROGMEM character array named
* "usbHidReportDescriptor" to your code which contains the report descriptor.
* Don't forget to keep the array and this define in sync!
*/
/* #define USB_PUBLIC static */
/* Use the define above if you #include usbdrv.c instead of linking against it.
* This technique saves a couple of bytes in flash memory.
*/
/* ------------------- Fine Control over USB Descriptors ------------------- */
/* If you don't want to use the driver's default USB descriptors, you can
* provide our own. These can be provided as (1) fixed length static data in
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
* information about this function.
* Descriptor handling is configured through the descriptor's properties. If
* no properties are defined or if they are 0, the default descriptor is used.
* Possible properties are:
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
* you want RAM pointers.
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
* in static memory is in RAM, not in flash memory.
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
* the driver must know the descriptor's length. The descriptor itself is
* found at the address of a well known identifier (see below).
* List of static descriptor names (must be declared PROGMEM if in flash):
* char usbDescriptorDevice[];
* char usbDescriptorConfiguration[];
* char usbDescriptorHidReport[];
* char usbDescriptorString0[];
* int usbDescriptorStringVendor[];
* int usbDescriptorStringDevice[];
* int usbDescriptorStringSerialNumber[];
* Other descriptors can't be provided statically, they must be provided
* dynamically at runtime.
*
* Descriptor properties are or-ed or added together, e.g.:
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
*
* The following descriptors are defined:
* USB_CFG_DESCR_PROPS_DEVICE
* USB_CFG_DESCR_PROPS_CONFIGURATION
* USB_CFG_DESCR_PROPS_STRINGS
* USB_CFG_DESCR_PROPS_STRING_0
* USB_CFG_DESCR_PROPS_STRING_VENDOR
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
* USB_CFG_DESCR_PROPS_HID
* USB_CFG_DESCR_PROPS_HID_REPORT
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
*
* Note about string descriptors: String descriptors are not just strings, they
* are Unicode strings prefixed with a 2 byte header. Example:
* int serialNumberDescriptor[] = {
* USB_STRING_DESCRIPTOR_HEADER(6),
* 'S', 'e', 'r', 'i', 'a', 'l'
* };
*/
#define USB_CFG_DESCR_PROPS_DEVICE 0
#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
#define USB_CFG_DESCR_PROPS_STRINGS 0
#define USB_CFG_DESCR_PROPS_STRING_0 0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
#define USB_CFG_DESCR_PROPS_HID 0
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
/* ----------------------- Optional MCU Description ------------------------ */
/* The following configurations have working defaults in usbdrv.h. You
* usually don't need to set them explicitly. Only if you want to run
* the driver on a device which is not yet supported or with a compiler
* which is not fully supported (such as IAR C) or if you use a differnt
* interrupt than INT0, you may have to define some of these.
*/
/* #define USB_INTR_CFG MCUCR */
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
/* #define USB_INTR_CFG_CLR 0 */
/* #define USB_INTR_ENABLE GIMSK */
/* #define USB_INTR_ENABLE_BIT INT0 */
/* #define USB_INTR_PENDING GIFR */
/* #define USB_INTR_PENDING_BIT INTF0 */
/* #define USB_INTR_VECTOR SIG_INTERRUPT0 */
#endif /* __usbconfig_h_included__ */

View File

@@ -268,3 +268,10 @@ Scroll down to the bottom to see the most recent changes.
- Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser.
* Release 2009-03-23
- Hid-mouse example used settings from hid-data example, fixed that.
- Renamed project to V-USB due to a trademark issue with Atmel(r).
- Changed CommercialLicense.txt and USBID-License.txt to make the
background of USB ID registration clearer.
* Release 2009-04-15

View File

@@ -1,5 +1,5 @@
AVR-USB Driver Software License Agreement
Version 2008-10-07
V-USB Driver Software License Agreement
Version 2009-04-14
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
@@ -13,8 +13,8 @@ Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA.
1.2 "You" shall mean the Licensee.
1.3 "AVR-USB" shall mean all files included in the package distributed under
the name "avrusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/avrusb/)
1.3 "V-USB" shall mean all files included in the package distributed under
the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/)
unless otherwise noted. This includes the firmware-only USB device
implementation for Atmel AVR microcontrollers, some simple device examples
and host side software examples and libraries.
@@ -23,21 +23,22 @@ and host side software examples and libraries.
2 LICENSE GRANTS
2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source
code of AVR-USB.
code of V-USB.
2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the
non-exclusive right to use, copy and distribute AVR-USB with your hardware
non-exclusive right to use, copy and distribute V-USB with your hardware
product(s), restricted by the limitations in section 3 below.
2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify
the source code and your copy of AVR-USB according to your needs.
the source code and your copy of V-USB according to your needs.
2.4 USB IDs. OBJECTIVE DEVELOPMENT grants you the exclusive rights to use
USB Product ID(s) sent to you in e-mail after receiving your payment in
conjunction with USB Vendor ID 5824. OBJECTIVE DEVELOPMENT has acquired an
exclusive license for this pair of USB identifiers from Wouter van Ooijen
(www.voti.nl), who has licensed the VID from the USB Implementers Forum,
Inc. (www.usb.org).
2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB Product
ID(s), sent to you in e-mail. These Product IDs are reserved exclusively for
you. They have been obtained from Wouter van Ooijen (www.voti.nl), who has
reserved the Vendor ID 5824 (decimal) at the USB Implementers Forum, Inc.
(www.usb.org). This mechanism ensures that there are no Product ID conflicts,
but you cannot become USB certified (enter into the USB-IF Trademark License
Agreement) as you would need your own Vendor ID for that.
3 LICENSE RESTRICTIONS
@@ -46,21 +47,21 @@ Inc. (www.usb.org).
applicable. Which one is determined by the amount you pay to OBJECTIVE
DEVELOPMENT, see section 4 ("Payment") below.
Hobby License: You may use AVR-USB according to section 2 above in no more
Hobby License: You may use V-USB according to section 2 above in no more
than 5 hardware units. These units must not be sold for profit.
Entry Level License: You may use AVR-USB according to section 2 above in no
Entry Level License: You may use V-USB according to section 2 above in no
more than 150 hardware units.
Professional License: You may use AVR-USB according to section 2 above in
Professional License: You may use V-USB according to section 2 above in
any number of hardware units, except for large scale production ("unlimited
fair use"). Quantities below 10,000 units are not considered large scale
production. If your reach quantities which are obviously large scale
production, you must pay a license fee of 0.10 EUR per unit for all units
above 10,000.
3.2 Rental. You may not rent, lease, or lend AVR-USB or otherwise encumber
any copy of AVR-USB, or any of the rights granted herein.
3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber
any copy of V-USB, or any of the rights granted herein.
3.3 Transfer. You may not transfer your rights under this Agreement to
another party without OBJECTIVE DEVELOPMENT's prior written consent. If
@@ -78,7 +79,7 @@ non-exclusive.
by third parties. In particular, you are not allowed to use the USB logo or
other trademarks owned by the USB Implementers Forum, Inc. without their
consent. Since such consent depends on USB certification, it should be
noted that AVR-USB will not pass certification because it does not
noted that V-USB will not pass certification because it does not
implement checksum verification and the microcontroller ports do not meet
the electrical specifications.
@@ -88,15 +89,15 @@ the electrical specifications.
The payment amount depends on the variation of this agreement (according to
section 3.1) into which you want to enter. Concrete prices are listed on
OBJECTIVE DEVELOPMENT's web site, usually at
http://www.obdev.at/avrusb/license.html. You agree to pay the amount listed
http://www.obdev.at/vusb/license.html. You agree to pay the amount listed
there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor
or reseller.
5 COPYRIGHT AND OWNERSHIP
AVR-USB is protected by copyright laws and international copyright
treaties, as well as other intellectual property laws and treaties. AVR-USB
V-USB is protected by copyright laws and international copyright
treaties, as well as other intellectual property laws and treaties. V-USB
is licensed, not sold.
@@ -112,12 +113,12 @@ and limitation of liability shall survive termination of this agreement.
7 DISCLAIMER OF WARRANTY AND LIABILITY
LIMITED WARRANTY. AVR-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE
DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
NON-INFRINGEMENT, WITH REGARD TO AVR-USB, AND THE PROVISION OF OR FAILURE
NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE
TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO
STATE/JURISDICTION.
@@ -127,11 +128,11 @@ IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY
SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
(INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE AVR-USB OR THE
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE
PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE
DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY
CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR AVR-USB.
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB.
8 MISCELLANEOUS TERMS

View File

@@ -1,18 +1,18 @@
OBJECTIVE DEVELOPMENT GmbH's AVR-USB driver software is distributed under the
OBJECTIVE DEVELOPMENT GmbH's V-USB driver software is distributed under the
terms and conditions of the GNU GPL version 2 or the GNU GPL version 3. It is
your choice whether you apply the terms of version 2 or version 3. The full
text of GPLv2 is included below. In addition to the requirements in the GPL,
we STRONGLY ENCOURAGE you to do the following:
(1) Publish your entire project on a web site and drop us a note with the URL.
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
(2) Adhere to minimum publication standards. Please include AT LEAST:
- a circuit diagram in PDF, PNG or GIF format
- full source code for the host software
- a Readme.txt file in ASCII format which describes the purpose of the
project and what can be found in which directories and which files
- a reference to http://www.obdev.at/avrusb/
- a reference to http://www.obdev.at/vusb/
(3) If you improve the driver firmware itself, please give us a free license
to your modifications for our commercial license offerings.

View File

@@ -1,6 +1,6 @@
This is the Readme file to Objective Development's firmware-only USB driver
for Atmel AVR microcontrollers. For more information please visit
http://www.obdev.at/avrusb/
http://www.obdev.at/vusb/
This directory contains the USB firmware only. Copy it as-is to your own
project and add all .c and .S files to your project (these files are marked
@@ -53,7 +53,7 @@ actual clock rate must be configured in usbdrv.h unless you use the default
12 MHz.
12 MHz Clock
This is the traditional clock rate of AVR-USB because it's the lowest clock
This is the traditional clock rate of V-USB because it's the lowest clock
rate where the timing constraints of the USB spec can be met.
15 MHz Clock
@@ -78,7 +78,7 @@ oscillator can reach 16.5 MHz with the RC oscillator. This includes the very
popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost
all AVRs can reach 12.8 MHz, although this is outside the specified range.
See the EasyLogger example at http://www.obdev.at/avrusb/easylogger.html for
See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for
code which calibrates the RC oscillator based on the USB frame clock.
18 MHz Clock
@@ -108,14 +108,14 @@ and hobbyists, we provide some VID/PID pairs for free. See the file
USBID-License.txt for details.
Objective Development also has some license offerings which include product
IDs. See http://www.obdev.at/avrusb/ for details.
IDs. See http://www.obdev.at/vusb/ for details.
DEVELOPMENT SYSTEM
==================
This driver has been developed and optimized for the GNU compiler version 3
(gcc 3). It does work well with gcc 4, but with bigger code size. We recommend
that you use the GNU compiler suite because it is freely available. AVR-USB
that you use the GNU compiler suite because it is freely available. V-USB
has also been ported to the IAR compiler and assembler. It has been tested
with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the "small" and "tiny"
memory model. Not every release is tested with IAR CC and the driver may
@@ -123,8 +123,8 @@ therefore fail to compile with IAR. Please note that gcc is more efficient for
usbdrv.c because this module has been deliberately optimized for gcc.
USING AVR-USB FOR FREE
======================
USING V-USB FOR FREE
====================
The AVR firmware driver is published under the GNU General Public License
Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is
your choice whether you apply the terms of version 2 or version 3.
@@ -133,26 +133,26 @@ If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the
following things IN ADDITION to the obligations from the GPL:
(1) Publish your entire project on a web site and drop us a note with the URL.
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
If you don't have a web site, you can publish the project in obdev's
documentation wiki at
http://www.obdev.at/goto.php?t=avrusb-wiki&p=hosted-projects.
http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects.
(2) Adhere to minimum publication standards. Please include AT LEAST:
- a circuit diagram in PDF, PNG or GIF format
- full source code for the host software
- a Readme.txt file in ASCII format which describes the purpose of the
project and what can be found in which directories and which files
- a reference to http://www.obdev.at/avrusb/
- a reference to http://www.obdev.at/vusb/
(3) If you improve the driver firmware itself, please give us a free license
to your modifications for our commercial license offerings.
COMMERCIAL LICENSES FOR AVR-USB
===============================
COMMERCIAL LICENSES FOR V-USB
=============================
If you don't want to publish your source code under the terms of the GPL,
you can simply pay money for AVR-USB. As an additional benefit you get
USB PIDs for free, licensed exclusively to you. See the file
you can simply pay money for V-USB. As an additional benefit you get
USB PIDs for free, reserved exclusively to you. See the file
"CommercialLicense.txt" for details.

View File

@@ -1,10 +1,17 @@
Royalty-Free Non-Exclusive License USB Product-ID
Royalty-Free Non-Exclusive Use of USB Product-IDs
=================================================
Version 2008-04-07
Version 2009-04-13
Strictly speaking, this is not a license. You can't give a license to use
a simple number (such as e.g. 1500) for any purpose. This is a set of rules
which should make it possible to build USB devices without the requirement
for individual USB IDs. If you break one of the rules, you will run into
technical problems sooner or later, but you don't risk legal trouble.
OBJECTIVE DEVELOPMENT Software GmbH hereby grants you the non-exclusive
right to use three USB.org vendor-ID (VID) / product-ID (PID) pairs with
right to use four USB.org vendor-ID (VID) / product-ID (PID) pairs with
products based on Objective Development's firmware-only USB driver for
Atmel AVR microcontrollers:
@@ -27,10 +34,11 @@ used by many companies and individuals for different products. To avoid
conflicts, your device and host driver software MUST adhere to the rules
outlined below.
OBJECTIVE DEVELOPMENT Software GmbH has licensed these VID/PID pairs from
Wouter van Ooijen (see www.voti.nl), who has licensed the VID from the USB
Implementers Forum, Inc. (see www.usb.org). The VID is registered for the
company name "Van Ooijen Technische Informatica".
OBJECTIVE DEVELOPMENT Software GmbH has obtained these VID/PID pairs from
Wouter van Ooijen (see www.voti.nl) for exclusive disposition. Wouter van
Ooijen has obtained the VID from the USB Implementers Forum, Inc.
(see www.usb.org). The VID is registered for the company name
"Van Ooijen Technische Informatica".
RULES AND RESTRICTIONS
@@ -44,7 +52,7 @@ MUST be available at least in USB language 0x0409 (English/US).
domain name (e.g. "mycompany.com") registered and owned by you, or an
e-mail address under your control (e.g. "myname@gmx.net"). You can embed
the domain name or e-mail address in any string you like, e.g. "Objective
Development http://www.obdev.at/avrusb/".
Development http://www.obdev.at/vusb/".
(3) You are responsible for retaining ownership of the domain or e-mail
address for as long as any of your products are in use.
@@ -142,5 +150,5 @@ violates the USB specification. If you do it, you do it at your own risk.
To avoid possible incompatibilities, we highly recommend that you get your
own VID/PID pair if you intend to sell your product. Objective
Development's commercial licenses for AVR-USB include a PID for
Development's commercial licenses for V-USB include a PID for
unrestricted exclusive use.

View File

@@ -1,5 +1,5 @@
/* Name: asmcommon.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-11-05
* Tabsize: 4

View File

@@ -1,11 +1,11 @@
/* Name: usbconfig.h
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2005-04-01
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbconfig-prototype.h 734 2009-03-23 11:10:07Z cs $
* This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
*/
#ifndef __usbconfig_h_included__
@@ -14,7 +14,7 @@
/*
General Description:
This file is an example configuration (with inline documentation) for the USB
driver. It configures AVR-USB for USB D+ connected to Port D bit 2 (which is
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
other hardware interrupt, as long as it is the highest level interrupt, see

View File

@@ -1,11 +1,11 @@
/* Name: usbdrv.c
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.c 721 2009-03-16 19:03:19Z cs $
* This Revision: $Id: usbdrv.c 740 2009-04-13 18:23:31Z cs $
*/
#include "usbportability.h"

View File

@@ -1,11 +1,11 @@
/* Name: usbdrv.h
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.h 738 2009-03-23 11:13:24Z cs $
* This Revision: $Id: usbdrv.h 748 2009-04-15 15:05:07Z cs $
*/
#ifndef __usbdrv_h_included__
@@ -122,7 +122,7 @@ USB messages, even if they address another (low-speed) device on the same bus.
/* --------------------------- Module Interface ---------------------------- */
/* ------------------------------------------------------------------------- */
#define USBDRV_VERSION 20090323
#define USBDRV_VERSION 20090415
/* This define uniquely identifies a driver version. It is a decimal number
* constructed from the driver's release date in the form YYYYMMDD. If the
* driver's behavior or interface changes, you can use this constant to

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm.S
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-06-13
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm.S 722 2009-03-16 19:03:57Z cs $
* Revision: $Id: usbdrvasm.S 740 2009-04-13 18:23:31Z cs $
*/
/*

View File

@@ -1,5 +1,5 @@
/* Name: usbdrvasm.asm
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2006-03-01
* Tabsize: 4

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm12.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm12.inc 692 2008-11-07 15:07:40Z cs $
* This Revision: $Id: usbdrvasm12.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm128.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2008-10-11
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm128.inc 692 2008-11-07 15:07:40Z cs $
* This Revision: $Id: usbdrvasm128.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm15.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: contributed by V. Bosch
* Creation Date: 2007-08-06
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm15.inc 692 2008-11-07 15:07:40Z cs $
* Revision: $Id: usbdrvasm15.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm16.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-06-15
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm16.inc 692 2008-11-07 15:07:40Z cs $
* Revision: $Id: usbdrvasm16.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm165.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-04-22
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm165.inc 692 2008-11-07 15:07:40Z cs $
* Revision: $Id: usbdrvasm165.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -1,11 +1,11 @@
/* Name: usbdrvasm18.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Lukas Schrittwieser (based on 20 MHz usbdrvasm20.inc by Jeroen Benschop)
* Creation Date: 2009-01-20
* Tabsize: 4
* Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm18-crc.inc 734 2009-03-23 11:10:07Z cs $
* Revision: $Id: usbdrvasm18-crc.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -1,12 +1,12 @@
/* Name: usbdrvasm20.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Jeroen Benschop
* Based on usbdrvasm16.inc from Christian Starkjohann
* Creation Date: 2008-03-05
* Tabsize: 4
* Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm20.inc 692 2008-11-07 15:07:40Z cs $
* Revision: $Id: usbdrvasm20.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@@ -1,11 +1,11 @@
/* Name: usbportability.h
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2008-06-17
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbportability.h 692 2008-11-07 15:07:40Z cs $
* This Revision: $Id: usbportability.h 740 2009-04-13 18:23:31Z cs $
*/
/*

BIN
roms/arkanoid.smc Normal file

Binary file not shown.

BIN
roms/eric.smc Normal file

Binary file not shown.

BIN
roms/kirby.smc Normal file

Binary file not shown.

BIN
roms/super01.smc Normal file

Binary file not shown.

BIN
roms/super02.smc Normal file

Binary file not shown.

BIN
roms/turrican.smc Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

142
tools/bsnes/.cproject Normal file
View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<?fileVersion 4.0.0?>
<cproject>
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876" moduleId="org.eclipse.cdt.core.settings" name="MacOSX GCC">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.MachO" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="bsnes" buildProperties="" id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876" name="MacOSX GCC" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876.81319156" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.macosx.base.1621265583" name="cdt.managedbuild.toolchain.gnu.macosx.base" superClass="cdt.managedbuild.toolchain.gnu.macosx.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.MachO" id="cdt.managedbuild.target.gnu.platform.macosx.base.980966539" name="Debug Platform" osList="macosx" superClass="cdt.managedbuild.target.gnu.platform.macosx.base"/>
<builder id="cdt.managedbuild.target.gnu.builder.macosx.base.1148816406" managedBuildOn="false" name="Gnu Make Builder.MacOSX GCC" superClass="cdt.managedbuild.target.gnu.builder.macosx.base"/>
<tool id="cdt.managedbuild.tool.macosx.c.linker.macosx.base.18412343" name="MacOS X C Linker" superClass="cdt.managedbuild.tool.macosx.c.linker.macosx.base"/>
<tool id="cdt.managedbuild.tool.macosx.cpp.linker.macosx.base.951081191" name="MacOS X C++ Linker" superClass="cdt.managedbuild.tool.macosx.cpp.linker.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.assembler.macosx.base.672073602" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.macosx.base.1929224322" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.base.430483384" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.macosx.base.773198848" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.macosx.base"/>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="bsnes2.null.2078314739" name="bsnes2"/>
</storageModule>
</cproject>

78
tools/bsnes/.project Normal file
View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>bsnes</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
</natures>
</projectDescription>

View File

@@ -1,110 +1,109 @@
include lib/nall/Makefile.string
prefix = /usr/local
include lib/nall/Makefile
ui = ui_qt
platform=mac
compiler=gcc
enable_gzip=false
################
### compiler ###
################
ifneq ($(findstring gcc,$(compiler)),) # GCC family
flags = -O3 -fomit-frame-pointer -Ilib
# note: libco *requires* -fomit-frame-pointer on i386 arch
libcoflags := $(flags) -static
c = $(compiler)
cpp = $(subst cc,++,$(compiler))
obj = o
rule = -c $< -o $@
link = -s
mkbin = -o$1
mkdef = -D$1
mkincpath = -I$1
mklib = -l$1
mklibpath = -L$1
c := $(compiler)
cpp := $(subst cc,++,$(compiler))
flags := -ggdb3 -O3 -fomit-frame-pointer -Ilib
link :=
################
### platform ###
################
ifeq ($(platform),mac)
flags +=-I/Developer/SDKs/Qt/include \
-I/Developer/SDKs/Qt/include/QtCore \
-I/Developer/SDKs/Qt/include/QtGui \
-I/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers \
-I/System/Library/Frameworks/AGL.framework/Headers \
-I/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers \
-I/usr/X11R6/include \
-I/opt/local/include
link += -lz \
-lm \
-lao \
-framework ApplicationServices \
-framework OpenGL \
-framework OpenAL \
-framework AGL \
-L/opt/local/lib \
-lSDL -Wl,-framework,Cocoa \
-lXext \
-lgl \
-lX11
#ruby := video.glx video.sdl
#ruby += audio.openal audio.ao
#ruby += input.sdl
#-DVIDEO_GLX -DVIDEO_XV -DVIDEO_SDL -DAUDIO_ALS
#-DAUDIO_OPENAL -DAUDIO_OSS -DAUDIO_PULSEAUDIO
#-DAUDIO_AO -DINPUT_SDL -DINPUT_X
flags += -DVIDEO_SDL -DINPUT_SDL -DVIDEO_GLX -DAUDIO_AO -DAUDIO_OPENAL
# profile-guided optimization:
# flags += -fprofile-generate
# link += -lgcov
# flags += -fprofile-use
else ifeq ($(compiler),cl) # Visual C++
flags = /nologo /wd4355 /wd4805 /wd4996 /Ox /GL /EHsc /Ilib
libcoflags = $(flags)
c = cl
cpp = cl
obj = obj
rule = /c $< /Fo$@
link = /link
mkbin = /Fe$1
mkdef = /D$1
mkincpath = /I$1
mklib = $1.lib
mklibpath = /L$1
else
unknown_compiler: help;
endif
##########
### os ###
##########
ifeq ($(platform),x)
ruby := video.glx video.xv video.sdl
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
ruby += input.sdl input.x
else ifeq ($(platform),win)
ruby := video.direct3d video.wgl video.directdraw video.gdi
ruby += audio.directsound
ruby += input.rawinput input.directinput
ifeq ($(platform),x) # X11
ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x
delete = rm -f $1
else ifeq ($(platform),win) # Windows
mingw_link_flags = -mwindows
# mingw_links_flags = -mconsole
# enable static linking to Qt for Windows build
mingw_link_flags += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.rawinput input.directinput
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
link += $(if $(findstring mingw,$(compiler)),$(mingw_link_flags))
link += $(call mklib,uuid)
link += $(call mklib,kernel32)
link += $(call mklib,user32)
link += $(call mklib,gdi32)
link += $(call mklib,shell32)
else
unknown_platform: help;
link += -mwindows
link += -luuid -lkernel32 -luser32 -lgdi32 -lshell32
# statically link Qt for Windows build
link += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
endif
############
### ruby ###
############
rubyflags = $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`)
link += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
rubyflags = $(call ifhas,.sdl,$(ruby),`sdl-config --cflags`)
link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9))
link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw))
link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL))
link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32))
link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv))
link += $(if $(findstring audio.alsa,$(ruby)),$(call mklib,asound))
link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao))
link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
link += $(if $(findstring audio.pulseaudio,$(ruby)),$(call mklib,pulse-simple))
link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid))
link += $(if $(findstring input.rawinput,$(ruby)),$(call mklib,xinput) $(call mklib,dinput8) $(call mklib,dxguid))
link += $(call ifhas,.sdl,$(ruby),`sdl-config --libs`)
link += $(call ifhas,video.direct3d,$(ruby),-ld3d9)
link += $(call ifhas,video.directdraw,$(ruby),-lddraw)
link += $(call ifhas,video.glx,$(ruby),-lGL)
link += $(call ifhas,video.wgl,$(ruby),-lopengl32)
link += $(call ifhas,video.xv,$(ruby),-lXv)
link += $(call ifhas,audio.alsa,$(ruby),-lasound)
link += $(call ifhas,audio.ao,$(ruby),-lao)
link += $(call ifhas,audio.directsound,$(ruby),-ldsound)
link += $(call ifhas,audio.openal,$(ruby),$(if $(call streq,$(platform),x),-lopenal,-lopenal32))
link += $(call ifhas,audio.pulseaudio,$(ruby),-lpulse-simple)
link += $(call ifhas,input.directinput,$(ruby),-ldinput8 -ldxguid)
link += $(call ifhas,input.rawinput,$(ruby),-lxinput -ldinput8 -ldxguid)
####################
### core objects ###
####################
objects = libco ruby libfilter string \
reader cart cheat \
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \
bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
objects = libco ruby libreader libfilter string \
system cartridge cheat \
memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu \
sgb sa1 bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
ifeq ($(enable_gzip),true)
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
flags += $(call mkdef,GZIP_SUPPORT)
flags += -DGZIP_SUPPORT
endif
ifeq ($(enable_jma),true)
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
flags += $(call mkdef,JMA_SUPPORT)
flags += -DJMA_SUPPORT
endif
######################
@@ -114,134 +113,137 @@ endif
compile = \
$(strip \
$(if $(filter %.c,$<), \
$(c) $(flags) $1 $(rule), \
$(c) $(flags) $1 -c $< -o $@, \
$(if $(filter %.cpp,$<), \
$(cpp) $(flags) $1 $(rule) \
$(cpp) $(flags) $1 -c $< -o $@ \
) \
) \
)
%.$(obj): $<; $(call compile)
%.o: $<; $(call compile)
all: build;
include $(ui)/Makefile
objects := $(patsubst %,obj/%.$(obj),$(objects))
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
objects := $(patsubst %,obj/%.o,$(objects))
rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
#################
### libraries ###
#################
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/* lib/ruby/video/* lib/ruby/audio/* lib/ruby/input/*
obj/ruby.o: lib/ruby/ruby.cpp $(call rwildcard,lib/ruby/*)
$(call compile,$(rubydef) $(rubyflags))
obj/libco.$(obj): lib/libco/libco.c lib/libco/*
$(c) $(libcoflags) $(rule)
obj/libfilter.$(obj): lib/libfilter/libfilter.cpp lib/libfilter/*
obj/string.$(obj): lib/nall/string.cpp lib/nall/*
obj/libco.o: lib/libco/libco.c lib/libco/*
$(c) -O3 -fomit-frame-pointer -static -Ilib -c $< -o $@
obj/libreader.o: lib/libreader/libreader.cpp lib/libreader/*
obj/libfilter.o: lib/libfilter/libfilter.cpp lib/libfilter/*
obj/string.o: lib/nall/string.cpp lib/nall/*
#################
### utilities ###
#################
obj/reader.$(obj): reader/reader.cpp reader/*
obj/cart.$(obj) : cart/cart.cpp cart/*
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
obj/cartridge.o: cartridge/cartridge.cpp cartridge/*
obj/cheat.o : cheat/cheat.cpp cheat/*
##############
### memory ###
##############
obj/memory.$(obj) : memory/memory.cpp memory/*
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
obj/memory.o : memory/memory.cpp memory/*
obj/smemory.o: memory/smemory/smemory.cpp $(call rwildcard,memory/smemory/)
###########
### cpu ###
###########
obj/cpu.$(obj) : cpu/cpu.cpp cpu/*
obj/scpu.$(obj): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
obj/cpu.o : cpu/cpu.cpp cpu/*
obj/cpucore.o: cpu/core/core.cpp $(call rwildcard,cpu/core/)
obj/scpu.o : cpu/scpu/scpu.cpp $(call rwildcard,cpu/scpu/)
###########
### smp ###
###########
obj/smp.$(obj) : smp/smp.cpp smp/*
obj/ssmp.$(obj): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
obj/smp.o : smp/smp.cpp smp/*
obj/smpcore.o: smp/core/core.cpp $(call rwildcard,smp/core/)
obj/ssmp.o : smp/ssmp/ssmp.cpp $(call rwildcard,smp/ssmp/)
###########
### dsp ###
###########
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/*
obj/sdsp.$(obj): dsp/sdsp/sdsp.cpp dsp/sdsp/*
obj/adsp.o: dsp/adsp/adsp.cpp dsp/adsp/*
obj/sdsp.o: dsp/sdsp/sdsp.cpp dsp/sdsp/*
###########
### ppu ###
###########
obj/ppu.$(obj) : ppu/ppu.cpp ppu/*
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/*
obj/ppu.o : ppu/ppu.cpp ppu/*
obj/bppu.o: ppu/bppu/bppu.cpp ppu/bppu/*
############
### snes ###
############
##############
### system ###
##############
obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
obj/system.o: system/system.cpp $(call rwildcard,system/)
#####################
### special chips ###
#####################
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
obj/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/*
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/*
obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
obj/spc7110.o: chip/spc7110/spc7110.cpp chip/spc7110/*
obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
obj/st010.o : chip/st010/st010.cpp chip/st010/*
############
### zlib ###
############
obj/adler32.$(obj) : reader/zlib/adler32.c reader/zlib/*
obj/compress.$(obj): reader/zlib/compress.c reader/zlib/*
obj/crc32.$(obj) : reader/zlib/crc32.c reader/zlib/*
obj/deflate.$(obj) : reader/zlib/deflate.c reader/zlib/*
obj/gzio.$(obj) : reader/zlib/gzio.c reader/zlib/*
obj/inffast.$(obj) : reader/zlib/inffast.c reader/zlib/*
obj/inflate.$(obj) : reader/zlib/inflate.c reader/zlib/*
obj/inftrees.$(obj): reader/zlib/inftrees.c reader/zlib/*
obj/ioapi.$(obj) : reader/zlib/ioapi.c reader/zlib/*
obj/trees.$(obj) : reader/zlib/trees.c reader/zlib/*
obj/unzip.$(obj) : reader/zlib/unzip.c reader/zlib/*
obj/zip.$(obj) : reader/zlib/zip.c reader/zlib/*
obj/zutil.$(obj) : reader/zlib/zutil.c reader/zlib/*
obj/adler32.o : lib/zlib/adler32.c lib/zlib/*
obj/compress.o: lib/zlib/compress.c lib/zlib/*
obj/crc32.o : lib/zlib/crc32.c lib/zlib/*
obj/deflate.o : lib/zlib/deflate.c lib/zlib/*
obj/gzio.o : lib/zlib/gzio.c lib/zlib/*
obj/inffast.o : lib/zlib/inffast.c lib/zlib/*
obj/inflate.o : lib/zlib/inflate.c lib/zlib/*
obj/inftrees.o: lib/zlib/inftrees.c lib/zlib/*
obj/ioapi.o : lib/zlib/ioapi.c lib/zlib/*
obj/trees.o : lib/zlib/trees.c lib/zlib/*
obj/unzip.o : lib/zlib/unzip.c lib/zlib/*
obj/zip.o : lib/zlib/zip.c lib/zlib/*
obj/zutil.o : lib/zlib/zutil.c lib/zlib/*
###########
### jma ###
###########
##############
### libjma ###
##############
obj/jma.$(obj) : reader/jma/jma.cpp reader/jma/*
obj/jcrc32.$(obj) : reader/jma/jcrc32.cpp reader/jma/*
obj/lzmadec.$(obj): reader/jma/lzmadec.cpp reader/jma/*
obj/7zlzma.$(obj) : reader/jma/7zlzma.cpp reader/jma/*
obj/iiostrm.$(obj): reader/jma/iiostrm.cpp reader/jma/*
obj/inbyte.$(obj) : reader/jma/inbyte.cpp reader/jma/*
obj/lzma.$(obj) : reader/jma/lzma.cpp reader/jma/*
obj/winout.$(obj) : reader/jma/winout.cpp reader/jma/*
obj/jma.o : lib/libjma/jma.cpp lib/libjma/*
obj/jcrc32.o : lib/libjma/jcrc32.cpp lib/libjma/*
obj/lzmadec.o: lib/libjma/lzmadec.cpp lib/libjma/*
obj/7zlzma.o : lib/libjma/7zlzma.cpp lib/libjma/*
obj/iiostrm.o: lib/libjma/iiostrm.cpp lib/libjma/*
obj/inbyte.o : lib/libjma/inbyte.cpp lib/libjma/*
obj/lzma.o : lib/libjma/lzma.cpp lib/libjma/*
obj/winout.o : lib/libjma/winout.cpp lib/libjma/*
###############
### targets ###
###############
build: ui_build $(objects)
$(strip $(cpp) $(call mkbin,../bsnes) $(objects) $(link))
$(strip g++ -o bsnes $(objects) $(link))
install:
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
@@ -249,13 +251,7 @@ install:
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
clean: ui_clean
-@$(call delete,obj/*.$(obj))
-@$(call delete,*.res)
-@$(call delete,*.pgd)
-@$(call delete,*.pgc)
-@$(call delete,*.ilk)
-@$(call delete,*.pdb)
-@$(call delete,*.manifest)
rm obj/*.o
help:
@echo "Usage: $(MAKE) platform=(os) compiler=(cc) [options]"
@@ -268,7 +264,6 @@ help:
@echo " gcc - GCC compiler"
@echo " mingw32-gcc - MinGW compiler"
@echo " i586-mingw32-gcc - MinGW cross compiler"
@echo " cl - Visual C++"
@echo ""
@echo "Available options:"
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
@@ -276,3 +271,4 @@ help:
@echo ""
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
@echo ""

View File

@@ -1,4 +1,4 @@
#define BSNES_VERSION "0.042"
#define BSNES_VERSION "0.046"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BUSCORE sBus
@@ -9,12 +9,7 @@
//S-DSP can be encapsulated into a state machine using #define magic
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
#define USE_STATE_MACHINE
//FAST_FRAMESKIP disables calculation of RTO during frameskip
//frameskip offers near-zero speedup if RTO is calculated
//accuracy is not affected by this define when frameskipping is off
#define FAST_FRAMESKIP
#define DSP_STATE_MACHINE
//game genie + pro action replay code support (~2% speed hit)
#define CHEAT_SYSTEM
@@ -25,8 +20,9 @@
#include <nall/array.hpp>
#include <nall/bit.hpp>
#include <nall/detect.hpp>
#include <nall/dl.hpp>
#include <nall/endian.hpp>
#include <nall/file.hpp>
#include <nall/function.hpp>
#include <nall/moduloarray.hpp>
#include <nall/new.hpp>
#include <nall/platform.hpp>
@@ -40,10 +36,9 @@ using namespace nall;
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
#include "interface.hpp"

View File

@@ -1,234 +0,0 @@
#include <../base.hpp>
#include <../chip/chip.hpp>
#include <../reader/reader.hpp>
#define CART_CPP
#include <nall/crc32.hpp>
#include <nall/ups.hpp>
#include "cart.hpp"
#include "cart_file.cpp"
#include "cart_header.cpp"
#include "cart_loader.cpp"
namespace memory {
MappedRAM cartrom, cartram, cartrtc;
MappedRAM bscram;
MappedRAM stArom, stAram;
MappedRAM stBrom, stBram;
};
Cartridge cartridge;
void Cartridge::load_begin(Mode cartridge_mode) {
cart.rom = cart.ram = cart.rtc = 0;
bs.ram = 0;
stA.rom = stA.ram = 0;
stB.rom = stB.ram = 0;
cart.rom_size = cart.ram_size = cart.rtc_size = 0;
bs.ram_size = 0;
stA.rom_size = stA.ram_size = 0;
stB.rom_size = stB.ram_size = 0;
set(loaded, false);
set(bsx_flash_loaded, false);
set(patched, false);
set(mode, cartridge_mode);
}
void Cartridge::load_end() {
memory::cartrom.map(cart.rom, cart.rom_size);
memory::cartram.map(cart.ram, cart.ram_size);
memory::cartrtc.map(cart.rtc, cart.rtc_size);
memory::bscram.map(bs.ram, bs.ram_size);
memory::stArom.map(stA.rom, stA.rom_size);
memory::stAram.map(stA.ram, stA.ram_size);
memory::stBrom.map(stB.rom, stB.rom_size);
memory::stBram.map(stB.ram, stB.ram_size);
memory::cartrom.write_protect(true);
memory::cartram.write_protect(false);
memory::bscram.write_protect(true);
memory::stArom.write_protect(true);
memory::stAram.write_protect(false);
memory::stBrom.write_protect(true);
memory::stBram.write_protect(false);
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
if(file::exists(cheat_file)) {
cheat.clear();
cheat.load(cheat_file);
}
bus.load_cart();
set(loaded, true);
}
void Cartridge::unload() {
if(loaded() == false) return;
bus.unload_cart();
switch(mode()) {
case ModeNormal: unload_normal(); break;
case ModeBsxSlotted: unload_bsx_slotted(); break;
case ModeBsx: unload_bsx(); break;
case ModeSufamiTurbo: unload_sufami_turbo(); break;
}
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
if(cart.ram) { delete[] cart.ram; cart.ram = 0; }
if(cart.rtc) { delete[] cart.rtc; cart.rtc = 0; }
if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
if(cheat.count() > 0 || file::exists(cheat_file)) {
cheat.save(cheat_file);
cheat.clear();
}
set(loaded, false);
}
Cartridge::Cartridge() {
set(loaded, false);
}
Cartridge::~Cartridge() {
if(loaded() == true) unload();
}
void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
set(region, source.region);
set(mapper, source.mapper);
set(dsp1_mapper, source.dsp1_mapper);
set(has_bsx_slot, source.bsx_slot);
set(has_superfx, source.superfx);
set(has_sa1, source.sa1);
set(has_srtc, source.srtc);
set(has_sdd1, source.sdd1);
set(has_spc7110, source.spc7110);
set(has_spc7110rtc, source.spc7110rtc);
set(has_cx4, source.cx4);
set(has_dsp1, source.dsp1);
set(has_dsp2, source.dsp2);
set(has_dsp3, source.dsp3);
set(has_dsp4, source.dsp4);
set(has_obc1, source.obc1);
set(has_st010, source.st010);
set(has_st011, source.st011);
set(has_st018, source.st018);
}
//==========
//cartinfo_t
//==========
void Cartridge::cartinfo_t::reset() {
type = TypeUnknown;
mapper = LoROM;
dsp1_mapper = DSP1Unmapped;
region = NTSC;
rom_size = 0;
ram_size = 0;
bsx_slot = false;
superfx = false;
sa1 = false;
srtc = false;
sdd1 = false;
spc7110 = false;
spc7110rtc = false;
cx4 = false;
dsp1 = false;
dsp2 = false;
dsp3 = false;
dsp4 = false;
obc1 = false;
st010 = false;
st011 = false;
st018 = false;
}
Cartridge::cartinfo_t::cartinfo_t() {
reset();
}
//=======
//utility
//=======
//ensure file path is absolute (eg resolve relative paths)
string Cartridge::filepath(const char *filename, const char *pathname) {
//if no pathname, return filename as-is
string file(filename);
file.replace("\\", "/");
string path = (!pathname || !*pathname) ? (const char*)snes.config.path.current : pathname;
//ensure path ends with trailing '/'
path.replace("\\", "/");
if(!strend(path, "/")) path.append("/");
//replace relative path with absolute path
if(strbegin(path, "./")) {
ltrim(path, "./");
path = string() << snes.config.path.base << path;
}
//remove folder part of filename
lstring part;
part.split("/", file);
return path << part[part.size() - 1];
}
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
string Cartridge::basename(const char *filename) {
string name(filename);
//remove extension
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '.') {
name[i] = 0;
break;
}
}
//remove directory information
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
i++;
char *output = name();
while(true) {
*output++ = name[i];
if(!name[i]) break;
i++;
}
break;
}
}
return name;
}
//remove filename and return path only ("/foo/bar.ext" -> "/foo/bar/")
string Cartridge::basepath(const char *filename) {
string path(filename);
path.replace("\\", "/");
//remove filename
for(signed i = strlen(path) - 1; i >= 0; i--) {
if(path[i] == '/') {
path[i] = 0;
break;
}
}
if(!strend(path, "/")) path.append("/");
return path;
}

View File

@@ -1,178 +0,0 @@
class Cartridge : public property {
public:
enum Mode {
ModeNormal,
ModeBsxSlotted,
ModeBsx,
ModeSufamiTurbo,
};
enum Type {
TypeNormal,
TypeBsxSlotted,
TypeBsxBios,
TypeBsx,
TypeSufamiTurboBios,
TypeSufamiTurbo,
TypeUnknown,
};
enum Region {
NTSC,
PAL,
};
enum MemoryMapper {
LoROM,
HiROM,
ExLoROM,
ExHiROM,
SPC7110ROM,
BSCLoROM,
BSCHiROM,
BSXROM,
STROM,
};
enum DSP1MemoryMapper {
DSP1Unmapped,
DSP1LoROM1MB,
DSP1LoROM2MB,
DSP1HiROM,
};
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
//warning: if loaded() == false, no other property is considered valid!
property_t<bool> loaded; //is a base cartridge inserted?
property_t<bool> bsx_flash_loaded; //is a BS-X flash cart connected?
property_t<bool> patched; //has a UPS patch been applied?
property_t<string> name; //display name (filename sans path and extension)
property_t<Mode> mode;
property_t<Region> region;
property_t<MemoryMapper> mapper;
property_t<DSP1MemoryMapper> dsp1_mapper;
property_t<bool> has_bsx_slot;
property_t<bool> has_superfx;
property_t<bool> has_sa1;
property_t<bool> has_srtc;
property_t<bool> has_sdd1;
property_t<bool> has_spc7110, has_spc7110rtc;
property_t<bool> has_cx4;
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
property_t<bool> has_obc1;
property_t<bool> has_st010, has_st011, has_st018;
//main interface
bool load_normal (const char *base);
bool load_bsx_slotted (const char *base, const char *slot = "");
bool load_bsx (const char *base, const char *slot = "");
bool load_sufami_turbo(const char *base, const char *slotA = "", const char *slotB = "");
void unload();
//utility functions
static string filepath(const char *filename, const char *pathname); //"./bar.ext" -> "/foo/bar.ext"
static string basename(const char *filename); //"/foo/bar.ext" -> "bar"
static string basepath(const char *filename); //"/foo/bar.ext" -> "/foo/bar/"
//this function will load 'filename', decompress it if needed, and determine what type of
//image file 'filename' refers to (eg normal cart, BS-X flash cart, Sufami Turbo cart, etc.)
//warning: this operation is very expensive, use sparingly!
Type detect_image_type(const char *filename) const;
Cartridge();
~Cartridge();
private:
void load_begin(Mode);
void load_end();
void unload_normal();
void unload_bsx_slotted();
void unload_bsx();
void unload_sufami_turbo();
struct cartinfo_t {
Type type;
Region region;
MemoryMapper mapper;
DSP1MemoryMapper dsp1_mapper;
unsigned rom_size, ram_size;
bool bsx_slot;
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool spc7110, spc7110rtc;
bool cx4;
bool dsp1, dsp2, dsp3, dsp4;
bool obc1;
bool st010, st011, st018;
void reset();
cartinfo_t();
};
enum HeaderField {
CartName = 0x00,
Mapper = 0x15,
RomType = 0x16,
RomSize = 0x17,
RamSize = 0x18,
CartRegion = 0x19,
Company = 0x1a,
Version = 0x1b,
Complement = 0x1c, //inverse checksum
Checksum = 0x1e,
ResetVector = 0x3c,
};
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
unsigned find_header(const uint8_t *data, unsigned size) const;
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
void set_cartinfo(const cartinfo_t&);
bool load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const;
bool load_ram (const char *filename, uint8_t *&data, unsigned size, uint8_t init_value) const;
enum CompressionMode {
CompressionNone, //always load without compression
CompressionInspect, //use file header inspection
CompressionAuto, //use file extension or file header inspection (configured by user)
};
bool load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression = CompressionNone) const;
bool save_file(const char *fn, uint8 *data, unsigned size) const;
bool apply_patch(const uint8_t *pdata, unsigned psize, uint8_t *&data, unsigned &size) const;
string modify_extension(const char *filename, const char *extension) const;
string get_filename(const char *source, const char *extension, const char *path) const;
struct {
string filename;
uint8_t *rom, *ram, *rtc;
unsigned rom_size, ram_size, rtc_size;
} cart;
struct {
string filename;
uint8_t *ram;
unsigned ram_size;
} bs;
struct {
string filename;
uint8_t *rom, *ram;
unsigned rom_size, ram_size;
} stA, stB;
};
namespace memory {
extern MappedRAM cartrom, cartram, cartrtc;
extern MappedRAM bscram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
};
extern Cartridge cartridge;

View File

@@ -1,109 +0,0 @@
#ifdef CART_CPP
#include "../reader/filereader.hpp"
#if defined(GZIP_SUPPORT)
#include "../reader/gzreader.hpp"
#include "../reader/zipreader.hpp"
#endif
#if defined(JMA_SUPPORT)
#include "../reader/jmareader.hpp"
#endif
string Cartridge::modify_extension(const char *filename_, const char *extension) const {
string filename = filename_;
int i;
for(i = strlen(filename); i >= 0; i--) {
if(filename[i] == '.') break;
if(filename[i] == '/') break;
if(filename[i] == '\\') break;
}
if(i > 0 && filename[i] == '.') filename[i] = 0;
return filename << "." << extension;
}
string Cartridge::get_filename(const char *source, const char *extension, const char *path) const {
return filepath(modify_extension(source, extension), path);
}
bool Cartridge::load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression) const {
if(file::exists(fn) == false) return false;
Reader::Type filetype = Reader::Normal;
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
if(compression == CompressionAuto) filetype = Reader::detect(fn, snes.config.file.autodetect_type);
switch(filetype) { default:
case Reader::Normal: {
FileReader ff(fn);
if(!ff.ready()) return false;
size = ff.size();
data = ff.read();
} break;
#ifdef GZIP_SUPPORT
case Reader::GZIP: {
GZReader gf(fn);
if(!gf.ready()) return false;
size = gf.size();
data = gf.read();
} break;
case Reader::ZIP: {
ZipReader zf(fn);
if(!zf.ready()) return false;
size = zf.size();
data = zf.read();
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::JMA: {
try {
JMAReader jf(fn);
size = jf.size();
data = jf.read();
} catch(JMA::jma_errors jma_error) {
return false;
}
} break;
#endif
}
return true;
}
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) const {
uint8_t *outdata = 0;
unsigned outsize;
ups patcher;
ups::result result = patcher.apply(pdata, psize, data, size, outdata, outsize);
bool apply = false;
if(result == ups::ok) apply = true;
if(snes.config.file.bypass_patch_crc32 == true) {
if(result == ups::input_crc32_invalid) apply = true;
if(result == ups::output_crc32_invalid) apply = true;
}
//if patch application was successful, replace old data, size with new data, size
if(apply == true) {
delete[] data;
data = new uint8_t[size = outsize];
memcpy(data, outdata, outsize);
}
if(outdata) delete[] outdata;
return apply;
}
bool Cartridge::save_file(const char *fn, uint8 *data, unsigned size) const {
file fp;
if(!fp.open(fn, file::mode_write)) return false;
fp.write(data, size);
fp.close();
return true;
}
#endif

View File

@@ -1,244 +0,0 @@
#ifdef CART_CPP
//================
//Normal cartridge
//================
bool Cartridge::load_normal(const char *base) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
load_begin(ModeNormal);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(cartinfo.ram_size > 0) {
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
}
if(cartinfo.srtc || cartinfo.spc7110rtc) {
load_ram(get_filename(base, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size = 20, 0x00);
}
load_end();
set(name, basename(base));
return true;
}
void Cartridge::unload_normal() {
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
if(cart.rtc) save_file(get_filename(cart.filename, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size);
}
//======================
//BS-X slotted cartridge
//======================
bool Cartridge::load_bsx_slotted(const char *base, const char *slot) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
bs.filename = slot;
load_begin(ModeBsxSlotted);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(load_image(slot, data, size, patch_applied) == true) {
set(bsx_flash_loaded, true);
if(patch_applied) set(patched, true);
bs.ram = data;
bs.ram_size = size;
}
if(cartinfo.ram_size > 0) {
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
}
load_end();
string filename = basename(base);
if(*slot) filename << " + " << basename(slot);
set(name, filename);
return true;
}
void Cartridge::unload_bsx_slotted() {
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
}
//====================
//BS-X flash cartridge
//====================
bool Cartridge::load_bsx(const char *base, const char *slot) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
bs.filename = slot;
load_begin(ModeBsx);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
cart.ram = 0;
cart.ram_size = 0;
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
if(load_file(get_filename(base, "srm", snes.config.path.save), data, size, CompressionNone) == true) {
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
delete[] data;
}
if(load_file(get_filename(base, "psr", snes.config.path.save), data, size, CompressionNone) == true) {
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
delete[] data;
}
if(load_image(slot, data, size, patch_applied) == true) {
set(bsx_flash_loaded, true);
if(patch_applied) set(patched, true);
bs.ram = data;
bs.ram_size = size;
}
load_end();
set(name, !*slot ? basename(base) : basename(slot));
return true;
}
void Cartridge::unload_bsx() {
save_file(get_filename(cart.filename, "srm", snes.config.path.save), bsxcart.sram.handle (), bsxcart.sram.size ());
save_file(get_filename(cart.filename, "psr", snes.config.path.save), bsxcart.psram.handle(), bsxcart.psram.size());
}
//============================
//Sufami Turbo flash cartridge
//============================
bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const char *slotB) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
stA.filename = slotA;
stB.filename = slotB;
load_begin(ModeSufamiTurbo);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(load_image(slotA, data, size, patch_applied) == true) {
if(patch_applied) set(patched, true);
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
memcpy(stA.rom, data, min(size, stA.rom_size));
delete[] data;
load_ram(get_filename(slotA, "srm", snes.config.path.save), stA.ram, stA.ram_size = 0x020000, 0xff);
}
if(load_image(slotB, data, size, patch_applied) == true) {
if(patch_applied) set(patched, true);
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
memcpy(stB.rom, data, min(size, stB.rom_size));
delete[] data;
load_ram(get_filename(slotB, "srm", snes.config.path.save), stB.ram, stB.ram_size = 0x020000, 0xff);
}
load_end();
string filename;
if(!*slotA && !*slotB) filename << basename(base);
else if( *slotA && !*slotB) filename << basename(slotA);
else if(!*slotA && *slotB) filename << basename(slotB);
else filename << basename(slotA) << " + " << basename(slotB);
set(name, filename);
return true;
}
void Cartridge::unload_sufami_turbo() {
if(stA.ram) save_file(get_filename(stA.filename, "srm", snes.config.path.save), stA.ram, stA.ram_size);
if(stB.ram) save_file(get_filename(stB.filename, "srm", snes.config.path.save), stB.ram, stB.ram_size);
}
//=================
//utility functions
//=================
Cartridge::Type Cartridge::detect_image_type(const char *filename) const {
uint8_t *data;
unsigned size;
bool patch_applied;
if(!load_image(filename, data, size, patch_applied)) return TypeUnknown;
cartinfo_t info;
read_header(info, data, size);
delete[] data;
return info.type;
}
bool Cartridge::load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const {
if(!filename || !*filename) return false;
if(!load_file(filename, data, size, CompressionAuto)) return false;
if((size & 0x7fff) == 512) {
//remove 512-byte header
memmove(data, data + 512, size -= 512);
}
uint8_t *pdata;
unsigned psize;
if(load_file(get_filename(filename, "ups", snes.config.path.patch), pdata, psize, CompressionInspect) == true) {
apply_patch(pdata, psize, data, size);
delete[] pdata;
patched = true;
} else {
patched = false;
}
return true;
}
bool Cartridge::load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init) const {
data = new uint8_t[size];
memset(data, init, size);
uint8_t *savedata;
unsigned savesize;
if(load_file(filename, savedata, savesize, CompressionNone) == false) return false;
memcpy(data, savedata, min(size, savesize));
delete[] savedata;
return true;
}
#endif

View File

@@ -0,0 +1,157 @@
#include <../base.hpp>
#define CARTRIDGE_CPP
namespace SNES {
#include "header.cpp"
namespace memory {
MappedRAM cartrom, cartram, cartrtc;
MappedRAM bsxflash, bsxram, bsxpram;
MappedRAM stArom, stAram;
MappedRAM stBrom, stBram;
MappedRAM gbrom, gbram;
};
Cartridge cartridge;
void Cartridge::load(Mode cartridge_mode) {
cartinfo_t cartinfo;
read_header(cartinfo, memory::cartrom.data(), memory::cartrom.size());
set_cartinfo(cartinfo);
set(mode, cartridge_mode);
if(cartinfo.ram_size > 0) {
memory::cartram.map(new(zeromemory) uint8_t[cartinfo.ram_size], cartinfo.ram_size);
}
if(cartinfo.srtc || cartinfo.spc7110rtc) {
memory::cartrtc.map(new(zeromemory) uint8_t[20], 20);
}
if(mode() == ModeBsx) {
memory::bsxram.map (new(zeromemory) uint8_t[ 32 * 1024], 32 * 1024);
memory::bsxpram.map(new(zeromemory) uint8_t[512 * 1024], 512 * 1024);
}
if(mode() == ModeSufamiTurbo) {
if(memory::stArom.data()) memory::stAram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
if(memory::stBrom.data()) memory::stBram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
}
if(mode() == ModeSuperGameBoy) {
if(memory::gbrom.data()) memory::gbram.map(new(zeromemory) uint8_t[64 * 1024], 64 * 1024);
}
memory::cartrom.write_protect(true);
memory::cartram.write_protect(false);
memory::cartrtc.write_protect(false);
memory::bsxflash.write_protect(true);
memory::bsxram.write_protect(false);
memory::bsxpram.write_protect(false);
memory::stArom.write_protect(true);
memory::stAram.write_protect(false);
memory::stBrom.write_protect(true);
memory::stBram.write_protect(false);
memory::gbrom.write_protect(true);
memory::gbram.write_protect(false);
bus.load_cart();
set(loaded, true);
}
void Cartridge::unload() {
memory::cartrom.reset();
memory::cartram.reset();
memory::cartrtc.reset();
memory::bsxflash.reset();
memory::bsxram.reset();
memory::bsxpram.reset();
memory::stArom.reset();
memory::stAram.reset();
memory::stBrom.reset();
memory::stBram.reset();
memory::gbrom.reset();
memory::gbram.reset();
if(loaded() == false) return;
bus.unload_cart();
set(loaded, false);
}
Cartridge::Type Cartridge::detect_image_type(uint8_t *data, unsigned size) const {
cartinfo_t info;
read_header(info, data, size);
return info.type;
}
Cartridge::Cartridge() {
set(loaded, false);
unload();
}
Cartridge::~Cartridge() {
unload();
}
void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
set(region, source.region);
set(mapper, source.mapper);
set(dsp1_mapper, source.dsp1_mapper);
set(has_bsx_slot, source.bsx_slot);
set(has_superfx, source.superfx);
set(has_sa1, source.sa1);
set(has_srtc, source.srtc);
set(has_sdd1, source.sdd1);
set(has_spc7110, source.spc7110);
set(has_spc7110rtc, source.spc7110rtc);
set(has_cx4, source.cx4);
set(has_dsp1, source.dsp1);
set(has_dsp2, source.dsp2);
set(has_dsp3, source.dsp3);
set(has_dsp4, source.dsp4);
set(has_obc1, source.obc1);
set(has_st010, source.st010);
set(has_st011, source.st011);
set(has_st018, source.st018);
}
//==========
//cartinfo_t
//==========
void Cartridge::cartinfo_t::reset() {
type = TypeUnknown;
mapper = LoROM;
dsp1_mapper = DSP1Unmapped;
region = NTSC;
rom_size = 0;
ram_size = 0;
bsx_slot = false;
superfx = false;
sa1 = false;
srtc = false;
sdd1 = false;
spc7110 = false;
spc7110rtc = false;
cx4 = false;
dsp1 = false;
dsp2 = false;
dsp3 = false;
dsp4 = false;
obc1 = false;
st010 = false;
st011 = false;
st018 = false;
}
Cartridge::cartinfo_t::cartinfo_t() {
reset();
}
};

View File

@@ -0,0 +1,130 @@
class Cartridge : public property {
public:
enum Mode {
ModeNormal,
ModeBsxSlotted,
ModeBsx,
ModeSufamiTurbo,
ModeSuperGameBoy,
};
enum Type {
TypeNormal,
TypeBsxSlotted,
TypeBsxBios,
TypeBsx,
TypeSufamiTurboBios,
TypeSufamiTurbo,
TypeSuperGameBoyBios,
TypeGameBoy,
TypeUnknown,
};
enum Region {
NTSC,
PAL,
};
enum MemoryMapper {
LoROM,
HiROM,
ExLoROM,
ExHiROM,
SA1ROM,
SPC7110ROM,
BSCLoROM,
BSCHiROM,
BSXROM,
STROM,
};
enum DSP1MemoryMapper {
DSP1Unmapped,
DSP1LoROM1MB,
DSP1LoROM2MB,
DSP1HiROM,
};
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
//warning: if loaded() == false, no other property is considered valid!
property_t<bool> loaded; //is a base cartridge inserted?
property_t<Mode> mode;
property_t<Region> region;
property_t<MemoryMapper> mapper;
property_t<DSP1MemoryMapper> dsp1_mapper;
property_t<bool> has_bsx_slot;
property_t<bool> has_superfx;
property_t<bool> has_sa1;
property_t<bool> has_srtc;
property_t<bool> has_sdd1;
property_t<bool> has_spc7110, has_spc7110rtc;
property_t<bool> has_cx4;
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
property_t<bool> has_obc1;
property_t<bool> has_st010, has_st011, has_st018;
//main interface
void load(Mode);
//void read();
//void load();
void unload();
Type detect_image_type(uint8_t *data, unsigned size) const;
Cartridge();
~Cartridge();
private:
struct cartinfo_t {
Type type;
Region region;
MemoryMapper mapper;
DSP1MemoryMapper dsp1_mapper;
unsigned rom_size, ram_size;
bool bsx_slot;
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool spc7110, spc7110rtc;
bool cx4;
bool dsp1, dsp2, dsp3, dsp4;
bool obc1;
bool st010, st011, st018;
void reset();
cartinfo_t();
};
enum HeaderField {
CartName = 0x00,
Mapper = 0x15,
RomType = 0x16,
RomSize = 0x17,
RamSize = 0x18,
CartRegion = 0x19,
Company = 0x1a,
Version = 0x1b,
Complement = 0x1c, //inverse checksum
Checksum = 0x1e,
ResetVector = 0x3c,
};
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
unsigned find_header(const uint8_t *data, unsigned size) const;
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
void set_cartinfo(const cartinfo_t&);
};
namespace memory {
extern MappedRAM cartrom, cartram, cartrtc;
extern MappedRAM bsxflash, bsxram, bsxpram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
extern MappedRAM gbrom, gbram;
};
extern Cartridge cartridge;

View File

@@ -1,8 +1,35 @@
#ifdef CART_CPP
#ifdef CARTRIDGE_CPP
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const {
info.reset();
unsigned index = find_header(data, size);
//=====================
//detect Game Boy carts
//=====================
if(size >= 0x0140) {
if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
&& data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
info.type = TypeGameBoy;
return;
}
}
const unsigned index = find_header(data, size);
const uint8 mapper = data[index + Mapper];
const uint8 rom_type = data[index + RomType];
const uint8 rom_size = data[index + RomSize];
const uint8 company = data[index + Company];
const uint8 region = data[index + CartRegion] & 0x7f;
if(data[index + RamSize] & 7) {
info.ram_size = 1024 << (data[index + RamSize] & 7);
} else {
info.ram_size = 0;
}
//0, 1, 13 = NTSC; 2 - 12 = PAL
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
//=======================
//detect BS-X flash carts
@@ -37,16 +64,19 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
return; //RAM size handled internally by load_cart_st();
}
//==========================
//detect Super Game Boy BIOS
//==========================
if(!memcmp(data + index, "Super GAMEBOY", 13)) {
info.type = TypeSuperGameBoyBios;
return;
}
//=====================
//detect standard carts
//=====================
const uint8 mapper = data[index + Mapper];
const uint8 rom_type = data[index + RomType];
const uint8 rom_size = data[index + RomSize];
const uint8 company = data[index + Company];
const uint8 region = data[index + CartRegion] & 0x7f;
//detect presence of BS-X flash cartridge connector (reads extended header information)
if(data[index - 14] == 'Z') {
if(data[index - 11] == 'J') {
@@ -91,8 +121,9 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
info.superfx = true;
}
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) {
if(mapper == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
info.sa1 = true;
info.mapper = SA1ROM;
}
if(mapper == 0x35 && rom_type == 0x55) {
@@ -162,15 +193,6 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
if(mapper == 0x30 && rom_type == 0xf5) {
info.st018 = true;
}
if(data[index + RamSize] & 7) {
info.ram_size = 1024 << (data[index + RamSize] & 7);
} else {
info.ram_size = 0;
}
//0, 1, 13 = NTSC; 2 - 12 = PAL
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
}
unsigned Cartridge::find_header(const uint8_t *data, unsigned size) const {

View File

@@ -1,3 +0,0 @@
::@mingw32-make platform=win compiler=mingw32-gcc
@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
@pause

View File

@@ -1,2 +0,0 @@
make platform=x compiler=gcc
#make platform=x compiler=gcc enable_gzip=true enable_jma=true

View File

@@ -1,5 +1,8 @@
#include <../base.hpp>
#define CHEAT_CPP
namespace SNES {
Cheat cheat;
Cheat::cheat_t& Cheat::cheat_t::operator=(const Cheat::cheat_t& source) {
@@ -178,9 +181,7 @@ void Cheat::disable(unsigned i) {
//...
//===============================
bool Cheat::load(const char *fn) {
string data;
if(!data.readfile(fn)) return false;
void Cheat::load(string data) {
data.replace("\r\n", "\n");
data.qreplace(" ", "");
@@ -193,21 +194,16 @@ bool Cheat::load(const char *fn) {
trim(part[0], "\"");
add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]);
}
return true;
}
bool Cheat::save(const char *fn) const {
file fp;
if(!fp.open(fn, file::mode_write)) return false;
string Cheat::save() const {
string data;
for(unsigned i = 0; i < code.size(); i++) {
fp.print(string()
<< "\"" << code[i].desc << "\", "
<< (code[i].enabled ? "enabled, " : "disabled, ")
<< code[i].code << "\r\n");
data << "\"" << code[i].desc << "\", "
<< (code[i].enabled ? "enabled, " : "disabled, ")
<< code[i].code << "\r\n";
}
fp.close();
return true;
return data;
}
void Cheat::clear() {
@@ -390,3 +386,6 @@ string& Cheat::decode_description(string &desc) const {
desc.replace("\\n", "\n");
return desc;
}
};

View File

@@ -38,8 +38,8 @@ public:
void enable(unsigned i);
void disable(unsigned i);
bool load(const char *fn);
bool save(const char *fn) const;
void load(string data);
string save() const;
void clear();
Cheat();

View File

@@ -1,8 +1,10 @@
#include <../base.hpp>
#include <../cart/cart.hpp>
#define BSX_CPP
#include "bsx.hpp"
#define BSX_CPP
namespace SNES {
#include "bsx_base.cpp"
#include "bsx_cart.cpp"
#include "bsx_flash.cpp"
};

View File

@@ -32,16 +32,10 @@ public:
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
MappedRAM sram;
MappedRAM psram;
BSXCart();
~BSXCart();
private:
uint8 *sram_data; //256kbit SRAM
uint8 *psram_data; // 4mbit PSRAM
struct {
uint8 r[16];
} regs;

View File

@@ -1,5 +1,7 @@
#ifdef BSX_CPP
BSXBase bsxbase;
void BSXBase::init() {
}
@@ -135,3 +137,4 @@ void BSXBase::mmio_write(unsigned addr, uint8 data) {
}
#endif

View File

@@ -1,5 +1,7 @@
#ifdef BSX_CPP
BSXCart bsxcart;
void BSXCart::init() {
}
@@ -20,7 +22,7 @@ void BSXCart::reset() {
}
void BSXCart::update_memory_map() {
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)memory::bsxpram;
if((regs.r[0x02] & 0x80) == 0x00) {
//LoROM mapping
@@ -35,16 +37,16 @@ void BSXCart::update_memory_map() {
}
if(regs.r[0x03] & 0x80) {
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram);
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
}
if((regs.r[0x05] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, psram);
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
}
if((regs.r[0x06] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, psram);
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
}
if(regs.r[0x07] & 0x80) {
@@ -55,8 +57,8 @@ void BSXCart::update_memory_map() {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
}
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram);
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram);
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
}
uint8 BSXCart::mmio_read(unsigned addr) {
@@ -66,7 +68,7 @@ uint8 BSXCart::mmio_read(unsigned addr) {
}
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
return memory::bsxram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
}
return 0x00;
@@ -81,21 +83,15 @@ void BSXCart::mmio_write(unsigned addr, uint8 data) {
}
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
return memory::bsxram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
}
}
BSXCart::BSXCart() {
sram_data = new uint8_t[ 32 * 1024];
psram_data = new uint8_t[512 * 1024];
sram.map (sram_data, 32 * 1024);
psram.map(psram_data, 512 * 1024);
}
BSXCart::~BSXCart() {
delete[] sram_data;
delete[] psram_data;
}
#endif

View File

@@ -1,5 +1,7 @@
#ifdef BSX_CPP
BSXFlash bsxflash;
void BSXFlash::init() {}
void BSXFlash::enable() {}
@@ -15,10 +17,11 @@ void BSXFlash::reset() {
regs.flash_enable = false;
regs.read_enable = false;
regs.write_enable = false;
memory::bsxflash.write_protect(!regs.write_enable);
}
unsigned BSXFlash::size() const {
return memory::bscram.size();
return memory::bsxflash.size();
}
uint8 BSXFlash::read(unsigned addr) {
@@ -45,7 +48,7 @@ uint8 BSXFlash::read(unsigned addr) {
}
}
return memory::bscram.read(addr);
return memory::bsxflash.read(addr);
}
void BSXFlash::write(unsigned addr, uint8 data) {
@@ -64,11 +67,11 @@ void BSXFlash::write(unsigned addr, uint8 data) {
regs.write_new = data;
if(regs.write_enable && regs.write_old == regs.write_new) {
return memory::bscram.write(addr, data);
return memory::bsxflash.write(addr, data);
}
} else {
if(regs.write_enable) {
return memory::bscram.write(addr, data);
return memory::bsxflash.write(addr, data);
}
}
@@ -107,7 +110,10 @@ void BSXFlash::write(unsigned addr, uint8 data) {
regs.read_enable = false;
regs.write_enable = false;
}
memory::bsxflash.write_protect(!regs.write_enable);
}
}
#endif

View File

@@ -1,3 +1,5 @@
#include "sgb/sgb.hpp"
#include "sa1/sa1.hpp"
#include "bsx/bsx.hpp"
#include "srtc/srtc.hpp"
#include "sdd1/sdd1.hpp"

View File

@@ -6,9 +6,12 @@
*/
#include <../base.hpp>
#define CX4_CPP
#include "cx4.hpp"
#define CX4_CPP
namespace SNES {
Cx4 cx4;
#include "cx4data.cpp"
#include "cx4fn.cpp"
#include "cx4oam.cpp"
@@ -30,8 +33,8 @@ uint16 addr = 0x0080 + (r * 3);
}
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
int64 rx = x & 0xffffff;
int64 ry = y & 0xffffff;
int64_t rx = x & 0xffffff;
int64_t ry = y & 0xffffff;
if(rx & 0x800000)rx |= ~0x7fffff;
if(ry & 0x800000)ry |= ~0x7fffff;
@@ -195,3 +198,5 @@ void Cx4::reset() {
memset(ram, 0, 0x0c00);
memset(reg, 0, 0x0100);
}
};

View File

@@ -1,8 +1,10 @@
#include <../base.hpp>
#include <../cart/cart.hpp>
#define DSP1_CPP
#include "dsp1.hpp"
#define DSP1_CPP
namespace SNES {
DSP1 dsp1;
#include "dsp1emu.cpp"
void DSP1::init() {}
@@ -57,3 +59,5 @@ void DSP1::write(unsigned addr, uint8 data) {
dsp1.setDr(data);
}
}
};

View File

@@ -1,7 +1,10 @@
#include <../base.hpp>
#define DSP2_CPP
#include "dsp2.hpp"
#define DSP2_CPP
namespace SNES {
DSP2 dsp2;
#include "dsp2_op.cpp"
void DSP2::init() {}
@@ -134,3 +137,5 @@ void DSP2::write(unsigned addr, uint8 data) {
DSP2::DSP2() {}
DSP2::~DSP2() {}
};

View File

@@ -1,7 +1,10 @@
#include <../base.hpp>
#define DSP3_CPP
#include "dsp3.hpp"
#define DSP3_CPP
namespace SNES {
DSP3 dsp3;
namespace DSP3i {
#define bool8 uint8
#include "dsp3emu.c"
@@ -33,3 +36,5 @@ void DSP3::write(unsigned addr, uint8 data) {
DSP3i::dsp3_byte = data;
DSP3i::DSP3SetByte();
}
};

View File

@@ -1,7 +1,10 @@
#include <../base.hpp>
#define DSP4_CPP
#include "dsp4.hpp"
#define DSP4_CPP
namespace SNES {
DSP4 dsp4;
namespace DSP4i {
inline uint16 READ_WORD(uint8 *addr) {
return (addr[0]) + (addr[1] << 8);
@@ -53,3 +56,5 @@ void DSP4::write(unsigned addr, uint8 data) {
DSP4i::DSP4SetByte();
}
}
};

View File

@@ -1,6 +1,9 @@
#include <../base.hpp>
#include <../cart/cart.hpp>
#include "obc1.hpp"
#define OBC1_CPP
namespace SNES {
OBC1 obc1;
void OBC1::init() {}
void OBC1::enable() {}
@@ -21,7 +24,7 @@ uint8 OBC1::read(unsigned addr) {
addr &= 0x1fff;
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
switch(addr) { default: //never used, avoids compiler warning
switch(addr) { default: //never used, avoids compiler warning
case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
@@ -70,3 +73,6 @@ void OBC1::ram_write(unsigned addr, uint8 data) {
OBC1::OBC1() {}
OBC1::~OBC1() {}
};

164
tools/bsnes/chip/sa1/bus/bus.cpp Executable file
View File

@@ -0,0 +1,164 @@
#ifdef SA1_CPP
SA1Bus sa1bus;
namespace memory {
VectorSelectionPage vectorsp;
StaticRAM iram(2048);
MappedRAM &bwram = memory::cartram;
CC1BWRAM cc1bwram;
BitmapRAM bitmapram;
}
void SA1Bus::init() {
for(uint32_t i = 0x0000; i <= 0xffff; i++) {
map(i << 8, memory::memory_unmapped, 0);
}
for(uint16_t i = 0x2200; i <= 0x23ff; i++) {
memory::mmio.map(i, sa1);
}
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
map(MapDirect, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram);
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bwram);
map(MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
map(MapDirect, 0x80, 0xbf, 0x2200, 0x23ff, memory::mmio);
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram);
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
bus.map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
bus.map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram);
bus.map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
bus.map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cc1bwram);
bus.map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
bus.map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram);
bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
bus.map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
memory::vectorsp.sync();
}
//===================
//VectorSelectionPage
//===================
//this class maps $00:[ff00-ffff] for the purpose of supporting:
//$2209.d6 IVSW (S-CPU IRQ vector selection) (0 = cart, 1 = SA-1)
//$2209.d4 NVSW (S-CPU NMI vector selection) (0 = cart, 1 = SA-1)
//when set, vector addresses are over-ridden with SA-1 register settings:
//SIV = S-CPU IRQ vector address override
//SNV = S-CPU NMI vector address override
//
//$00:[ffea-ffeb|ffee-ffef] are special cased on read;
//all other addresses return original mapped data.
uint8_t VectorSelectionPage::read(unsigned addr) {
switch(0xff00 | (addr & 0xff)) {
case 0xffea: case 0xffeb: {
if(sa1.mmio.cpu_nvsw == true) return (sa1.mmio.snv >> ((addr & 1) << 3));
} break;
case 0xffee: case 0xffef: {
if(sa1.mmio.cpu_ivsw == true) return (sa1.mmio.siv >> ((addr & 1) << 3));
} break;
}
return access->read(addr);
}
void VectorSelectionPage::write(unsigned addr, uint8_t data) {
return access->write(addr, data);
}
//call this whenever bus is remapped.
//note: S-CPU and SA-1 bus always share $00:[ff00-ffff] as cartridge ROM data;
//the SA-1 MMC does not allow mapping these independently between processors.
//this allows this class to be shared for both, caching only ones' access class.
void VectorSelectionPage::sync() {
if(bus.page[0x00ff00 >> 8].access != this) {
//bus was re-mapped, hook access routine
access = bus.page[0x00ff00 >> 8].access;
bus.page[0x00ff00 >> 8].access = this;
sa1bus.page[0x00ff00 >> 8].access = this;
}
}
//========
//CC1BWRAM
//========
unsigned CC1BWRAM::size() const {
return memory::cartram.size();
}
uint8_t CC1BWRAM::read(unsigned addr) {
if(dma) return sa1.dma_cc1_read(addr);
return memory::cartram.read(addr);
}
void CC1BWRAM::write(unsigned addr, uint8_t data) {
memory::cartram.write(addr, data);
}
//=========
//BitmapRAM
//=========
unsigned BitmapRAM::size() const {
return 0x100000;
}
uint8_t BitmapRAM::read(unsigned addr) {
if(sa1.mmio.bbf == 0) {
//4bpp
unsigned shift = addr & 1;
addr = (addr >> 1) & (memory::cartram.size() - 1);
switch(shift) {
case 0: return (memory::cartram.read(addr) >> 0) & 15;
case 1: return (memory::cartram.read(addr) >> 4) & 15;
}
} else {
//2bpp
unsigned shift = addr & 3;
addr = (addr >> 2) & (memory::cartram.size() - 1);
switch(shift) {
case 0: return (memory::cartram.read(addr) >> 0) & 3;
case 1: return (memory::cartram.read(addr) >> 2) & 3;
case 2: return (memory::cartram.read(addr) >> 4) & 3;
case 3: return (memory::cartram.read(addr) >> 6) & 3;
}
}
}
void BitmapRAM::write(unsigned addr, uint8_t data) {
if(sa1.mmio.bbf == 0) {
//4bpp
uint8_t shift = addr & 1;
addr = (addr >> 1) & (memory::cartram.size() - 1);
switch(shift) {
case 0: data = (memory::cartram.read(addr) & 0xf0) | ((data & 15) << 0); break;
case 1: data = (memory::cartram.read(addr) & 0x0f) | ((data & 15) << 4); break;
}
} else {
//2bpp
uint8_t shift = addr & 3;
addr = (addr >> 2) & (memory::cartram.size() - 1);
switch(shift) {
case 0: data = (memory::cartram.read(addr) & 0xfc) | ((data & 3) << 0); break;
case 1: data = (memory::cartram.read(addr) & 0xf3) | ((data & 3) << 2); break;
case 2: data = (memory::cartram.read(addr) & 0xcf) | ((data & 3) << 4); break;
case 3: data = (memory::cartram.read(addr) & 0x3f) | ((data & 3) << 6); break;
}
}
memory::cartram.write(addr, data);
}
#endif

View File

@@ -0,0 +1,31 @@
struct SA1Bus : Bus {
void init();
};
struct VectorSelectionPage : Memory {
alwaysinline uint8_t read(unsigned);
alwaysinline void write(unsigned, uint8_t);
void sync();
Memory *access;
};
struct CC1BWRAM : Memory {
unsigned size() const;
alwaysinline uint8_t read(unsigned);
alwaysinline void write(unsigned, uint8_t);
bool dma;
};
struct BitmapRAM : Memory {
unsigned size() const;
alwaysinline uint8_t read(unsigned);
alwaysinline void write(unsigned, uint8_t);
};
namespace memory {
extern VectorSelectionPage vectorsp;
extern StaticRAM iram;
extern MappedRAM &bwram;
extern CC1BWRAM cc1bwram;
extern BitmapRAM bitmapram;
}

139
tools/bsnes/chip/sa1/dma/dma.cpp Executable file
View File

@@ -0,0 +1,139 @@
#ifdef SA1_CPP
//====================
//direct data transfer
//====================
void SA1::dma_normal() {
while(mmio.dtc--) {
uint8_t data = regs.mdr;
uint32_t dsa = mmio.dsa++;
uint32_t dda = mmio.dda++;
//source and destination cannot be the same
if(mmio.sd == DMA::SourceBWRAM && mmio.dd == DMA::DestBWRAM) continue;
if(mmio.sd == DMA::SourceIRAM && mmio.dd == DMA::DestIRAM ) continue;
switch(mmio.sd) {
case DMA::SourceROM: {
if((dsa & 0x408000) == 0x008000 || (dsa & 0xc00000) == 0xc00000) {
data = sa1bus.read(dsa);
}
} break;
case DMA::SourceBWRAM: {
if((dsa & 0x40e000) == 0x006000 || (dsa & 0xf00000) == 0x400000) {
data = sa1bus.read(dsa);
}
} break;
case DMA::SourceIRAM: {
data = memory::iram.read(dsa & 0x07ff);
} break;
}
switch(mmio.dd) {
case DMA::DestBWRAM: {
if((dda & 0x40e000) == 0x006000 || (dda & 0xf00000) == 0x400000) {
sa1bus.write(dda, data);
}
} break;
case DMA::DestIRAM: {
memory::iram.write(dda & 0x07ff, data);
} break;
}
}
mmio.dma_irqfl = true;
if(mmio.dma_irqen) mmio.dma_irqcl = 0;
}
//((byte & 6) << 3) + (byte & 1) explanation:
//transforms a byte index (0-7) into a planar index:
//result[] = { 0, 1, 16, 17, 32, 33, 48, 49 };
//works for 2bpp, 4bpp and 8bpp modes
//===========================
//type-1 character conversion
//===========================
void SA1::dma_cc1() {
memory::cc1bwram.dma = true;
mmio.chdma_irqfl = true;
if(mmio.chdma_irqen) {
mmio.chdma_irqcl = 0;
cpu.regs.irq = 1;
}
}
uint8_t SA1::dma_cc1_read(unsigned addr) {
//16 bytes/char (2bpp); 32 bytes/char (4bpp); 64 bytes/char (8bpp)
unsigned charmask = (1 << (6 - mmio.dmacb)) - 1;
if((addr & charmask) == 0) {
//buffer next character to I-RAM
unsigned bpp = 2 << (2 - mmio.dmacb);
unsigned bpl = (8 << mmio.dmasize) >> mmio.dmacb;
unsigned bwmask = memory::bwram.size() - 1;
unsigned tile = ((addr - mmio.dsa) & bwmask) >> (6 - mmio.dmacb);
unsigned ty = (tile >> mmio.dmasize);
unsigned tx = tile & ((1 << mmio.dmasize) - 1);
unsigned bwaddr = mmio.dsa + ty * 8 * bpl + tx * bpp;
for(unsigned y = 0; y < 8; y++) {
uint64_t data = 0;
for(unsigned byte = 0; byte < bpp; byte++) {
data |= (uint64_t)memory::bwram.read((bwaddr + byte) & bwmask) << (byte << 3);
}
bwaddr += bpl;
uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
for(unsigned x = 0; x < 8; x++) {
out[0] |= (data & 1) << (7 - x); data >>= 1;
out[1] |= (data & 1) << (7 - x); data >>= 1;
if(mmio.dmacb == 2) continue;
out[2] |= (data & 1) << (7 - x); data >>= 1;
out[3] |= (data & 1) << (7 - x); data >>= 1;
if(mmio.dmacb == 1) continue;
out[4] |= (data & 1) << (7 - x); data >>= 1;
out[5] |= (data & 1) << (7 - x); data >>= 1;
out[6] |= (data & 1) << (7 - x); data >>= 1;
out[7] |= (data & 1) << (7 - x); data >>= 1;
}
for(unsigned byte = 0; byte < bpp; byte++) {
unsigned p = mmio.dda + (y << 1) + ((byte & 6) << 3) + (byte & 1);
memory::iram.write(p & 0x07ff, out[byte]);
}
}
}
return memory::iram.read((mmio.dda + (addr & charmask)) & 0x07ff);
}
//===========================
//type-2 character conversion
//===========================
void SA1::dma_cc2() {
//select register file index (0-7 or 8-15)
const uint8_t *brf = &mmio.brf[(dma.line & 1) << 3];
unsigned bpp = 2 << (2 - mmio.dmacb);
unsigned addr = mmio.dda & 0x07ff;
addr &= ~((1 << (7 - mmio.dmacb)) - 1);
addr += (dma.line & 8) * bpp;
addr += (dma.line & 7) * 2;
for(unsigned byte = 0; byte < bpp; byte++) {
uint8_t output = 0;
for(unsigned bit = 0; bit < 8; bit++) {
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
}
memory::iram.write(addr + ((byte & 6) << 3) + (byte & 1), output);
}
dma.line = (dma.line + 1) & 15;
}
#endif

View File

@@ -0,0 +1,11 @@
struct DMA {
enum CDEN { DmaNormal = 0, DmaCharConversion = 1 };
enum SD { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 };
enum DD { DestIRAM = 0, DestBWRAM = 1 };
unsigned line;
} dma;
void dma_normal();
void dma_cc1();
uint8_t dma_cc1_read(unsigned addr);
void dma_cc2();

View File

@@ -0,0 +1,39 @@
#ifdef SA1_CPP
//==========================
//SA-1 opcode core functions
//==========================
void SA1::op_io() {
tick();
if(regs.wai) scheduler.sync_copcpu();
}
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
//BW-RAM is accessed at ~5.37MHz (4 clock ticks)
//tick() == 2 clock ticks
//note: bus conflict delays are not emulated at this time
#define is_bwram(addr) (\
((addr & 0x40e000) == 0x006000) \
|| ((addr & 0xf00000) == 0x400000) \
|| ((addr & 0xf00000) == 0x600000) \
)
uint8_t SA1::op_read(unsigned addr) {
tick();
if(is_bwram(addr)) tick();
scheduler.sync_copcpu();
return sa1bus.read(addr);
}
void SA1::op_write(unsigned addr, uint8_t data) {
tick();
if(is_bwram(addr)) tick();
scheduler.sync_copcpu();
sa1bus.write(addr, data);
}
#undef is_bwram
#endif

View File

@@ -0,0 +1,4 @@
alwaysinline void op_io();
alwaysinline uint8_t op_read(unsigned addr);
alwaysinline void op_write(unsigned addr, uint8_t data);
alwaysinline unsigned bus_speed(unsigned addr);

View File

@@ -0,0 +1,631 @@
#ifdef SA1_CPP
//BS-X flash carts, when present, are mapped to 0x400000+
Memory& SA1::mmio_access(unsigned &addr) {
if(!memory::bsxflash.data()) return memory::cartrom;
if(addr < 0x400000) return memory::cartrom;
addr &= 0x3fffff;
return bsxflash;
}
//(CCNT) SA-1 control
void SA1::mmio_w2200(uint8_t data) {
if(mmio.sa1_resb && !(data & 0x80)) {
//reset SA-1 CPU
regs.pc.w = mmio.crv;
regs.pc.b = 0x00;
}
mmio.sa1_irq = (data & 0x80);
mmio.sa1_rdyb = (data & 0x40);
mmio.sa1_resb = (data & 0x20);
mmio.sa1_nmi = (data & 0x10);
mmio.smeg = (data & 0x0f);
if(mmio.sa1_irq) {
mmio.sa1_irqfl = true;
if(mmio.sa1_irqen) mmio.sa1_irqcl = 0;
}
if(mmio.sa1_nmi) {
mmio.sa1_nmifl = true;
if(mmio.sa1_nmien) mmio.sa1_nmicl = 0;
}
}
//(SIE) S-CPU interrupt enable
void SA1::mmio_w2201(uint8_t data) {
if(!mmio.cpu_irqen && (data & 0x80)) {
if(mmio.cpu_irqfl) {
mmio.cpu_irqcl = 0;
cpu.regs.irq = 1;
}
}
if(!mmio.chdma_irqen && (data & 0x20)) {
if(mmio.chdma_irqfl) {
mmio.chdma_irqcl = 0;
cpu.regs.irq = 1;
}
}
mmio.cpu_irqen = (data & 0x80);
mmio.chdma_irqen = (data & 0x20);
}
//(SIC) S-CPU interrupt clear
void SA1::mmio_w2202(uint8_t data) {
mmio.cpu_irqcl = (data & 0x80);
mmio.chdma_irqcl = (data & 0x20);
if(mmio.cpu_irqcl ) mmio.cpu_irqfl = false;
if(mmio.chdma_irqcl) mmio.chdma_irqfl = false;
if(!mmio.cpu_irqfl && !mmio.chdma_irqfl) cpu.regs.irq = 0;
}
//(CRV) SA-1 reset vector
void SA1::mmio_w2203(uint8_t data) { mmio.crv = (mmio.crv & 0xff00) | data; }
void SA1::mmio_w2204(uint8_t data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
//(CNV) SA-1 NMI vector
void SA1::mmio_w2205(uint8_t data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }
void SA1::mmio_w2206(uint8_t data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
//(CIV) SA-1 IRQ vector
void SA1::mmio_w2207(uint8_t data) { mmio.civ = (mmio.civ & 0xff00) | data; }
void SA1::mmio_w2208(uint8_t data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
//(SCNT) S-CPU control
void SA1::mmio_w2209(uint8_t data) {
mmio.cpu_irq = (data & 0x80);
mmio.cpu_ivsw = (data & 0x40);
mmio.cpu_nvsw = (data & 0x10);
mmio.cmeg = (data & 0x0f);
if(mmio.cpu_irq) {
mmio.cpu_irqfl = true;
if(mmio.cpu_irqen) {
mmio.cpu_irqcl = 0;
cpu.regs.irq = 1;
}
}
}
//(CIE) SA-1 interrupt enable
void SA1::mmio_w220a(uint8_t data) {
if(!mmio.sa1_irqen && (data & 0x80) && mmio.sa1_irqfl ) mmio.sa1_irqcl = 0;
if(!mmio.timer_irqen && (data & 0x40) && mmio.timer_irqfl) mmio.timer_irqcl = 0;
if(!mmio.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0;
if(!mmio.sa1_nmien && (data & 0x10) && mmio.sa1_nmifl ) mmio.sa1_nmicl = 0;
mmio.sa1_irqen = (data & 0x80);
mmio.timer_irqen = (data & 0x40);
mmio.dma_irqen = (data & 0x20);
mmio.sa1_nmien = (data & 0x10);
}
//(CIC) SA-1 interrupt clear
void SA1::mmio_w220b(uint8_t data) {
mmio.sa1_irqcl = (data & 0x80);
mmio.timer_irqcl = (data & 0x40);
mmio.dma_irqcl = (data & 0x20);
mmio.sa1_nmicl = (data & 0x10);
if(mmio.sa1_irqcl) mmio.sa1_irqfl = false;
if(mmio.timer_irqcl) mmio.timer_irqfl = false;
if(mmio.dma_irqcl) mmio.dma_irqfl = false;
if(mmio.sa1_nmicl) mmio.sa1_nmifl = false;
}
//(SNV) S-CPU NMI vector
void SA1::mmio_w220c(uint8_t data) { mmio.snv = (mmio.snv & 0xff00) | data; }
void SA1::mmio_w220d(uint8_t data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
//(SIV) S-CPU IRQ vector
void SA1::mmio_w220e(uint8_t data) { mmio.siv = (mmio.siv & 0xff00) | data; }
void SA1::mmio_w220f(uint8_t data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
//(TMC) H/V timer control
void SA1::mmio_w2210(uint8_t data) {
mmio.hvselb = (data & 0x80);
mmio.ven = (data & 0x02);
mmio.hen = (data & 0x01);
}
//(CTR) SA-1 timer restart
void SA1::mmio_w2211(uint8_t data) {
status.vcounter = 0;
status.hcounter = 0;
}
//(HCNT) H-count
void SA1::mmio_w2212(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
void SA1::mmio_w2213(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
//(VCNT) V-count
void SA1::mmio_w2214(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
void SA1::mmio_w2215(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
//(CXB) Super MMC bank C
void SA1::mmio_w2220(uint8_t data) {
mmio.cbmode = (data & 0x80);
mmio.cb = (data & 0x07);
unsigned addr = mmio.cb << 20;
Memory &access = mmio_access(addr);
if(mmio.cbmode == 0) {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
} else {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
memory::vectorsp.sync();
}
//(DXB) Super MMC bank D
void SA1::mmio_w2221(uint8_t data) {
mmio.dbmode = (data & 0x80);
mmio.db = (data & 0x07);
unsigned addr = mmio.db << 20;
Memory &access = mmio_access(addr);
if(mmio.dbmode == 0) {
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
} else {
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
}
//(EXB) Super MMC bank E
void SA1::mmio_w2222(uint8_t data) {
mmio.ebmode = (data & 0x80);
mmio.eb = (data & 0x07);
unsigned addr = mmio.eb << 20;
Memory &access = mmio_access(addr);
if(mmio.ebmode == 0) {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
} else {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
}
//(FXB) Super MMC bank F
void SA1::mmio_w2223(uint8_t data) {
mmio.fbmode = (data & 0x80);
mmio.fb = (data & 0x07);
unsigned addr = mmio.fb << 20;
Memory &access = mmio_access(addr);
if(mmio.fbmode == 0) {
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
} else {
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
}
//(BMAPS) S-CPU BW-RAM address mapping
void SA1::mmio_w2224(uint8_t data) {
mmio.sbm = (data & 0x1f);
bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
}
//(BMAP) SA-1 BW-RAM address mapping
void SA1::mmio_w2225(uint8_t data) {
mmio.sw46 = (data & 0x80);
mmio.cbm = (data & 0x7f);
if(mmio.sw46 == 0) {
//$[40-43]:[0000-ffff] x 32 projection
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
} else {
//$[60-6f]:[0000-ffff] x 128 projection
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
}
}
//(SWBE) S-CPU BW-RAM write enable
void SA1::mmio_w2226(uint8_t data) {
mmio.swen = (data & 0x80);
}
//(CWBE) SA-1 BW-RAM write enable
void SA1::mmio_w2227(uint8_t data) {
mmio.cwen = (data & 0x80);
}
//(BWPA) BW-RAM write-protected area
void SA1::mmio_w2228(uint8_t data) {
mmio.bwp = (data & 0x0f);
}
//(SIWP) S-CPU I-RAM write protection
void SA1::mmio_w2229(uint8_t data) {
mmio.siwp = data;
}
//(CIWP) SA-1 I-RAM write protection
void SA1::mmio_w222a(uint8_t data) {
mmio.ciwp = data;
}
//(DCNT) DMA control
void SA1::mmio_w2230(uint8_t data) {
mmio.dmaen = (data & 0x80);
mmio.dprio = (data & 0x40);
mmio.cden = (data & 0x20);
mmio.cdsel = (data & 0x10);
mmio.dd = (data & 0x04);
mmio.sd = (data & 0x03);
if(mmio.dmaen == 0) dma.line = 0;
}
//(CDMA) character conversion DMA parameters
void SA1::mmio_w2231(uint8_t data) {
mmio.chdend = (data & 0x80);
mmio.dmasize = (data >> 2) & 7;
mmio.dmacb = (data & 0x03);
if(mmio.chdend) memory::cc1bwram.dma = false;
if(mmio.dmasize > 5) mmio.dmasize = 5;
if(mmio.dmacb > 2) mmio.dmacb = 2;
}
//(SDA) DMA source device start address
void SA1::mmio_w2232(uint8_t data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
void SA1::mmio_w2233(uint8_t data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
void SA1::mmio_w2234(uint8_t data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
//(DDA) DMA destination start address
void SA1::mmio_w2235(uint8_t data) {
mmio.dda = (mmio.dda & 0xffff00) | (data << 0);
}
void SA1::mmio_w2236(uint8_t data) {
mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);
if(mmio.dmaen == true) {
if(mmio.cden == 0 && mmio.dd == DMA::DestIRAM) {
dma_normal();
} else if(mmio.cden == 1 && mmio.cdsel == 1) {
dma_cc1();
}
}
}
void SA1::mmio_w2237(uint8_t data) {
mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);
if(mmio.dmaen == true) {
if(mmio.cden == 0 && mmio.dd == DMA::DestBWRAM) {
dma_normal();
}
}
}
//(DTC) DMA terminal counter
void SA1::mmio_w2238(uint8_t data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
void SA1::mmio_w2239(uint8_t data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
//(BBF) BW-RAM bitmap format
void SA1::mmio_w223f(uint8_t data) {
mmio.bbf = (data & 0x80);
}
//(BRF) bitmap register files
void SA1::mmio_w2240(uint8_t data) { mmio.brf[ 0] = data; }
void SA1::mmio_w2241(uint8_t data) { mmio.brf[ 1] = data; }
void SA1::mmio_w2242(uint8_t data) { mmio.brf[ 2] = data; }
void SA1::mmio_w2243(uint8_t data) { mmio.brf[ 3] = data; }
void SA1::mmio_w2244(uint8_t data) { mmio.brf[ 4] = data; }
void SA1::mmio_w2245(uint8_t data) { mmio.brf[ 5] = data; }
void SA1::mmio_w2246(uint8_t data) { mmio.brf[ 6] = data; }
void SA1::mmio_w2247(uint8_t data) { mmio.brf[ 7] = data;
if(mmio.dmaen == true) {
if(mmio.cden == 1 && mmio.cdsel == 0) {
dma_cc2();
}
}
}
void SA1::mmio_w2248(uint8_t data) { mmio.brf[ 8] = data; }
void SA1::mmio_w2249(uint8_t data) { mmio.brf[ 9] = data; }
void SA1::mmio_w224a(uint8_t data) { mmio.brf[10] = data; }
void SA1::mmio_w224b(uint8_t data) { mmio.brf[11] = data; }
void SA1::mmio_w224c(uint8_t data) { mmio.brf[12] = data; }
void SA1::mmio_w224d(uint8_t data) { mmio.brf[13] = data; }
void SA1::mmio_w224e(uint8_t data) { mmio.brf[14] = data; }
void SA1::mmio_w224f(uint8_t data) { mmio.brf[15] = data;
if(mmio.dmaen == true) {
if(mmio.cden == 1 && mmio.cdsel == 0) {
dma_cc2();
}
}
}
//(MCNT) arithmetic control
void SA1::mmio_w2250(uint8_t data) {
mmio.acm = (data & 0x02);
mmio.md = (data & 0x01);
if(mmio.acm) mmio.mr = 0;
}
//(MAL) multiplicand / dividend low
void SA1::mmio_w2251(uint8_t data) {
mmio.ma = (mmio.ma & 0xff00) | data;
}
//(MAH) multiplicand / dividend high
void SA1::mmio_w2252(uint8_t data) {
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
}
//(MBL) multiplier / divisor low
void SA1::mmio_w2253(uint8_t data) {
mmio.mb = (mmio.mb & 0xff00) | data;
}
//(MBH) multiplier / divisor high
//multiplication / cumulative sum only resets MB
//division resets both MA and MB
void SA1::mmio_w2254(uint8_t data) {
mmio.mb = (data << 8) | (mmio.mb & 0x00ff);
if(mmio.acm == 0) {
if(mmio.md == 0) {
//signed multiplication
mmio.mr = (int16_t)mmio.ma * (int16_t)mmio.mb;
mmio.mb = 0;
} else {
//unsigned division
if(mmio.mb == 0) {
mmio.mr = 0;
} else {
int16_t quotient = (int16_t)mmio.ma / (uint16_t)mmio.mb;
uint16_t remainder = (int16_t)mmio.ma % (uint16_t)mmio.mb;
mmio.mr = (remainder << 16) | quotient;
}
mmio.ma = 0;
mmio.mb = 0;
}
} else {
//sigma (accumulative multiplication)
mmio.mr += (int16_t)mmio.ma * (int16_t)mmio.mb;
mmio.overflow = (mmio.mr >= (1ULL << 40));
mmio.mr &= (1ULL << 40) - 1;
mmio.mb = 0;
}
}
//(VBD) variable-length bit processing
void SA1::mmio_w2258(uint8_t data) {
mmio.hl = (data & 0x80);
mmio.vb = (data & 0x0f);
if(mmio.vb == 0) mmio.vb = 16;
if(mmio.hl == 0) {
//fixed mode
mmio.vbit += mmio.vb;
mmio.va += (mmio.vbit >> 3);
mmio.vbit &= 7;
}
}
//(VDA) variable-length bit game pak ROM start address
void SA1::mmio_w2259(uint8_t data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
void SA1::mmio_w225a(uint8_t data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
void SA1::mmio_w225b(uint8_t data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
//(SFR) S-CPU flag read
uint8_t SA1::mmio_r2300() {
uint8_t data;
data = mmio.cpu_irqfl << 7;
data |= mmio.cpu_ivsw << 6;
data |= mmio.chdma_irqfl << 5;
data |= mmio.cpu_nvsw << 4;
data |= mmio.cmeg;
return data;
}
//(CFR) SA-1 flag read
uint8_t SA1::mmio_r2301() {
uint8_t data;
data = mmio.sa1_irqfl << 7;
data |= mmio.timer_irqfl << 6;
data |= mmio.dma_irqfl << 5;
data |= mmio.sa1_nmifl << 4;
data |= mmio.smeg;
return data;
}
//(HCR) hcounter read
uint8_t SA1::mmio_r2302() {
//latch counters
mmio.hcr = status.hcounter >> 2;
mmio.vcr = status.vcounter;
return mmio.hcr >> 0; }
uint8_t SA1::mmio_r2303() { return mmio.hcr >> 8; }
//(VCR) vcounter read
uint8_t SA1::mmio_r2304() { return mmio.vcr >> 0; }
uint8_t SA1::mmio_r2305() { return mmio.vcr >> 8; }
//(MR) arithmetic result
uint8_t SA1::mmio_r2306() { return mmio.mr >> 0; }
uint8_t SA1::mmio_r2307() { return mmio.mr >> 8; }
uint8_t SA1::mmio_r2308() { return mmio.mr >> 16; }
uint8_t SA1::mmio_r2309() { return mmio.mr >> 24; }
uint8_t SA1::mmio_r230a() { return mmio.mr >> 32; }
//(OF) arithmetic overflow flag
uint8_t SA1::mmio_r230b() { return mmio.overflow << 7; }
//(VDPL) variable-length data read port low
uint8_t SA1::mmio_r230c() {
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
| (sa1bus.read(mmio.va + 1) << 8)
| (sa1bus.read(mmio.va + 2) << 16);
data >>= mmio.vbit;
return data >> 0;
}
//(VDPH) variable-length data read port high
uint8_t SA1::mmio_r230d() {
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
| (sa1bus.read(mmio.va + 1) << 8)
| (sa1bus.read(mmio.va + 2) << 16);
data >>= mmio.vbit;
if(mmio.hl == 1) {
//auto-increment mode
mmio.vbit += mmio.vb;
mmio.va += (mmio.vbit >> 3);
mmio.vbit &= 7;
}
return data >> 8;
}
//(VC) version code register
uint8_t SA1::mmio_r230e() {
return 0x01; //true value unknown
}
uint8_t SA1::mmio_read(unsigned addr) {
addr &= 0xffff;
switch(addr) {
case 0x2300: return mmio_r2300();
case 0x2301: return mmio_r2301();
case 0x2302: return mmio_r2302();
case 0x2303: return mmio_r2303();
case 0x2304: return mmio_r2304();
case 0x2305: return mmio_r2305();
case 0x2306: return mmio_r2306();
case 0x2307: return mmio_r2307();
case 0x2308: return mmio_r2308();
case 0x2309: return mmio_r2309();
case 0x230a: return mmio_r230a();
case 0x230b: return mmio_r230b();
case 0x230c: return mmio_r230c();
case 0x230d: return mmio_r230d();
case 0x230e: return mmio_r230e();
}
return 0x00;
}
void SA1::mmio_write(unsigned addr, uint8_t data) {
addr &= 0xffff;
switch(addr) {
case 0x2200: return mmio_w2200(data);
case 0x2201: return mmio_w2201(data);
case 0x2202: return mmio_w2202(data);
case 0x2203: return mmio_w2203(data);
case 0x2204: return mmio_w2204(data);
case 0x2205: return mmio_w2205(data);
case 0x2206: return mmio_w2206(data);
case 0x2207: return mmio_w2207(data);
case 0x2208: return mmio_w2208(data);
case 0x2209: return mmio_w2209(data);
case 0x220a: return mmio_w220a(data);
case 0x220b: return mmio_w220b(data);
case 0x220c: return mmio_w220c(data);
case 0x220d: return mmio_w220d(data);
case 0x220e: return mmio_w220e(data);
case 0x220f: return mmio_w220f(data);
case 0x2210: return mmio_w2210(data);
case 0x2211: return mmio_w2211(data);
case 0x2212: return mmio_w2212(data);
case 0x2213: return mmio_w2213(data);
case 0x2214: return mmio_w2214(data);
case 0x2215: return mmio_w2215(data);
case 0x2220: return mmio_w2220(data);
case 0x2221: return mmio_w2221(data);
case 0x2222: return mmio_w2222(data);
case 0x2223: return mmio_w2223(data);
case 0x2224: return mmio_w2224(data);
case 0x2225: return mmio_w2225(data);
case 0x2226: return mmio_w2226(data);
case 0x2227: return mmio_w2227(data);
case 0x2228: return mmio_w2228(data);
case 0x2229: return mmio_w2229(data);
case 0x222a: return mmio_w222a(data);
case 0x2230: return mmio_w2230(data);
case 0x2231: return mmio_w2231(data);
case 0x2232: return mmio_w2232(data);
case 0x2233: return mmio_w2233(data);
case 0x2234: return mmio_w2234(data);
case 0x2235: return mmio_w2235(data);
case 0x2236: return mmio_w2236(data);
case 0x2237: return mmio_w2237(data);
case 0x2238: return mmio_w2238(data);
case 0x2239: return mmio_w2239(data);
case 0x223f: return mmio_w223f(data);
case 0x2240: return mmio_w2240(data);
case 0x2241: return mmio_w2241(data);
case 0x2242: return mmio_w2242(data);
case 0x2243: return mmio_w2243(data);
case 0x2244: return mmio_w2244(data);
case 0x2245: return mmio_w2245(data);
case 0x2246: return mmio_w2246(data);
case 0x2247: return mmio_w2247(data);
case 0x2248: return mmio_w2248(data);
case 0x2249: return mmio_w2249(data);
case 0x224a: return mmio_w224a(data);
case 0x224b: return mmio_w224b(data);
case 0x224c: return mmio_w224c(data);
case 0x224d: return mmio_w224d(data);
case 0x224e: return mmio_w224e(data);
case 0x224f: return mmio_w224f(data);
case 0x2250: return mmio_w2250(data);
case 0x2251: return mmio_w2251(data);
case 0x2252: return mmio_w2252(data);
case 0x2253: return mmio_w2253(data);
case 0x2254: return mmio_w2254(data);
case 0x2258: return mmio_w2258(data);
case 0x2259: return mmio_w2259(data);
case 0x225a: return mmio_w225a(data);
case 0x225b: return mmio_w225b(data);
}
}
#endif

View File

@@ -0,0 +1,256 @@
uint8_t mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8_t data);
Memory& mmio_access(unsigned &addr);
struct MMIO {
//$2200 CCNT
bool sa1_irq;
bool sa1_rdyb;
bool sa1_resb;
bool sa1_nmi;
uint8_t smeg;
//$2201 SIE
bool cpu_irqen;
bool chdma_irqen;
//$2202 SIC
bool cpu_irqcl;
bool chdma_irqcl;
//$2203,$2204 CRV
uint16_t crv;
//$2205,$2206 CNV
uint16_t cnv;
//$2207,$2208 CIV
uint16_t civ;
//$2209 SCNT
bool cpu_irq;
bool cpu_ivsw;
bool cpu_nvsw;
uint8_t cmeg;
//$220a CIE
bool sa1_irqen;
bool timer_irqen;
bool dma_irqen;
bool sa1_nmien;
//$220b CIC
bool sa1_irqcl;
bool timer_irqcl;
bool dma_irqcl;
bool sa1_nmicl;
//$220c,$220d SNV
uint16_t snv;
//$220e,$220f SIV
uint16_t siv;
//$2210 TMC
bool hvselb;
bool ven;
bool hen;
//$2212,$2213
uint16_t hcnt;
//$2214,$2215
uint16_t vcnt;
//$2220 CXB
bool cbmode;
uint8_t cb;
//$2221 DXB
bool dbmode;
uint8_t db;
//$2222 EXB
bool ebmode;
uint8_t eb;
//$2223 FXB
bool fbmode;
uint8_t fb;
//$2224 BMAPS
uint8_t sbm;
//$2225 BMAP
bool sw46;
uint8_t cbm;
//$2226 SBWE
bool swen;
//$2227 CBWE
bool cwen;
//$2228 BWPA
uint8_t bwp;
//$2229 SIWP
uint8_t siwp;
//$222a CIWP
uint8_t ciwp;
//$2230 DCNT
bool dmaen;
bool dprio;
bool cden;
bool cdsel;
bool dd;
uint8_t sd;
//$2231 CDMA
bool chdend;
uint8_t dmasize;
uint8_t dmacb;
//$2232-$2234 SDA
uint32_t dsa;
//$2235-$2237 DDA
uint32_t dda;
//$2238,$2239 DTC
uint16_t dtc;
//$223f BBF
bool bbf;
//$2240-224f BRF
uint8_t brf[16];
//$2250 MCNT
bool acm;
bool md;
//$2251,$2252 MA
uint16_t ma;
//$2253,$2254 MB
uint16_t mb;
//$2258 VBD
bool hl;
uint8_t vb;
//$2259-$225b VDA
uint32_t va;
uint8_t vbit;
//$2300 SFR
bool cpu_irqfl;
bool chdma_irqfl;
//$2301 CFR
bool sa1_irqfl;
bool timer_irqfl;
bool dma_irqfl;
bool sa1_nmifl;
//$2302,$2303 HCR
uint16_t hcr;
//$2304,$2305 VCR
uint16_t vcr;
//$2306-230a MR
uint64_t mr;
//$230b OF
bool overflow;
} mmio;
void mmio_w2200(uint8_t); //CCNT
void mmio_w2201(uint8_t); //SIE
void mmio_w2202(uint8_t); //SIC
void mmio_w2203(uint8_t); //CRVL
void mmio_w2204(uint8_t); //CRVH
void mmio_w2205(uint8_t); //CNVL
void mmio_w2206(uint8_t); //CNVH
void mmio_w2207(uint8_t); //CIVL
void mmio_w2208(uint8_t); //CIVH
void mmio_w2209(uint8_t); //SCNT
void mmio_w220a(uint8_t); //CIE
void mmio_w220b(uint8_t); //CIC
void mmio_w220c(uint8_t); //SNVL
void mmio_w220d(uint8_t); //SNVH
void mmio_w220e(uint8_t); //SIVL
void mmio_w220f(uint8_t); //SIVH
void mmio_w2210(uint8_t); //TMC
void mmio_w2211(uint8_t); //CTR
void mmio_w2212(uint8_t); //HCNTL
void mmio_w2213(uint8_t); //HCNTH
void mmio_w2214(uint8_t); //VCNTL
void mmio_w2215(uint8_t); //VCNTH
void mmio_w2220(uint8_t); //CXB
void mmio_w2221(uint8_t); //DXB
void mmio_w2222(uint8_t); //EXB
void mmio_w2223(uint8_t); //FXB
void mmio_w2224(uint8_t); //BMAPS
void mmio_w2225(uint8_t); //BMAP
void mmio_w2226(uint8_t); //SBWE
void mmio_w2227(uint8_t); //CBWE
void mmio_w2228(uint8_t); //BWPA
void mmio_w2229(uint8_t); //SIWP
void mmio_w222a(uint8_t); //CIWP
void mmio_w2230(uint8_t); //DCNT
void mmio_w2231(uint8_t); //CDMA
void mmio_w2232(uint8_t); //SDAL
void mmio_w2233(uint8_t); //SDAH
void mmio_w2234(uint8_t); //SDAB
void mmio_w2235(uint8_t); //DDAL
void mmio_w2236(uint8_t); //DDAH
void mmio_w2237(uint8_t); //DDAB
void mmio_w2238(uint8_t); //DTCL
void mmio_w2239(uint8_t); //DTCH
void mmio_w223f(uint8_t); //BBF
void mmio_w2240(uint8_t); //BRF0
void mmio_w2241(uint8_t); //BRF1
void mmio_w2242(uint8_t); //BRF2
void mmio_w2243(uint8_t); //BRF3
void mmio_w2244(uint8_t); //BRF4
void mmio_w2245(uint8_t); //BRF5
void mmio_w2246(uint8_t); //BRF6
void mmio_w2247(uint8_t); //BRF7
void mmio_w2248(uint8_t); //BRF8
void mmio_w2249(uint8_t); //BRF9
void mmio_w224a(uint8_t); //BRFA
void mmio_w224b(uint8_t); //BRFB
void mmio_w224c(uint8_t); //BRFC
void mmio_w224d(uint8_t); //BRFD
void mmio_w224e(uint8_t); //BRFE
void mmio_w224f(uint8_t); //BRFF
void mmio_w2250(uint8_t); //MCNT
void mmio_w2251(uint8_t); //MAL
void mmio_w2252(uint8_t); //MAH
void mmio_w2253(uint8_t); //MBL
void mmio_w2254(uint8_t); //MBH
void mmio_w2258(uint8_t); //VBD
void mmio_w2259(uint8_t); //VDAL
void mmio_w225a(uint8_t); //VDAH
void mmio_w225b(uint8_t); //VDAB
uint8_t mmio_r2300(); //SFR
uint8_t mmio_r2301(); //CFR
uint8_t mmio_r2302(); //HCRL
uint8_t mmio_r2303(); //HCRH
uint8_t mmio_r2304(); //VCRL
uint8_t mmio_r2305(); //VCRH
uint8_t mmio_r2306(); //MR [00-07]
uint8_t mmio_r2307(); //MR [08-15]
uint8_t mmio_r2308(); //MR [16-23]
uint8_t mmio_r2309(); //MR [24-31]
uint8_t mmio_r230a(); //MR [32-40]
uint8_t mmio_r230b(); //OF
uint8_t mmio_r230c(); //VDPL
uint8_t mmio_r230d(); //VDPH
uint8_t mmio_r230e(); //VC

318
tools/bsnes/chip/sa1/sa1.cpp Executable file
View File

@@ -0,0 +1,318 @@
#include <../base.hpp>
#define SA1_CPP
namespace SNES {
SA1 sa1;
#include "bus/bus.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
void SA1::enter() {
while(true) {
while(mmio.sa1_rdyb || mmio.sa1_resb) {
//SA-1 co-processor is asleep
tick();
scheduler.sync_copcpu();
}
if(status.interrupt_pending) {
status.interrupt_pending = false;
interrupt(status.interrupt_vector);
}
(this->*opcode_table[op_readpc()])();
}
}
void SA1::last_cycle() {
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.cnv;
mmio.sa1_nmifl = true;
mmio.sa1_nmicl = 1;
regs.wai = false;
} else if(!regs.p.i) {
if(mmio.timer_irqen && !mmio.timer_irqcl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.civ;
mmio.timer_irqfl = true;
regs.wai = false;
} else if(mmio.dma_irqen && !mmio.dma_irqcl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.civ;
mmio.dma_irqfl = true;
regs.wai = false;
} else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.civ;
mmio.sa1_irqfl = true;
regs.wai = false;
}
}
}
void SA1::interrupt(uint16_t vector) {
op_read(regs.pc.d);
op_io();
if(!regs.e) op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
regs.pc.w = vector;
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
}
bool SA1::interrupt_pending() {
return status.interrupt_pending;
}
void SA1::tick() {
scheduler.addclocks_cop(2);
//adjust counters:
//note that internally, status counters are in clocks;
//whereas MMIO register counters are in dots (4 clocks = 1 dot)
if(mmio.hvselb == 0) {
//HV timer
status.hcounter += 2;
if(status.hcounter >= 1364) {
status.hcounter = 0;
if(++status.vcounter >= status.scanlines) status.vcounter = 0;
}
} else {
//linear timer
status.hcounter += 2;
status.vcounter += (status.hcounter >> 11);
status.hcounter &= 0x07ff;
status.vcounter &= 0x01ff;
}
//test counters for timer IRQ
switch((mmio.ven << 1) + (mmio.hen << 0)) {
case 0: break;
case 1: if(status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq(); break;
case 3: if(status.vcounter == mmio.hcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
}
}
void SA1::trigger_irq() {
mmio.timer_irqfl = true;
if(mmio.timer_irqen) mmio.timer_irqcl = 0;
}
void SA1::init() {
}
void SA1::enable() {
}
void SA1::power() {
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
reset();
}
void SA1::reset() {
memory::vectorsp.access = 0;
memory::cc1bwram.dma = false;
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
memory::iram.write(addr, 0x00);
}
sa1bus.init();
regs.pc.d = 0x000000;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
regs.wai = false;
update_table();
status.interrupt_pending = false;
status.interrupt_vector = 0x0000;
status.scanlines = (system.region() == System::NTSC ? 262 : 312);
status.vcounter = 0;
status.hcounter = 0;
dma.line = 0;
//$2200 CCNT
mmio.sa1_irq = false;
mmio.sa1_rdyb = false;
mmio.sa1_resb = true;
mmio.sa1_nmi = false;
mmio.smeg = 0;
//$2201 SIE
mmio.cpu_irqen = false;
mmio.chdma_irqen = false;
//$2202 SIC
mmio.cpu_irqcl = false;
mmio.chdma_irqcl = false;
//$2203,$2204 CRV
mmio.crv = 0x0000;
//$2205,$2206 CNV
mmio.cnv = 0x0000;
//$2207,$2208 CIV
mmio.civ = 0x0000;
//$2209 SCNT
mmio.cpu_irq = false;
mmio.cpu_ivsw = false;
mmio.cpu_nvsw = false;
mmio.cmeg = 0;
//$220a CIE
mmio.sa1_irqen = false;
mmio.timer_irqen = false;
mmio.dma_irqen = false;
mmio.sa1_nmien = false;
//$220b CIC
mmio.sa1_irqcl = false;
mmio.timer_irqcl = false;
mmio.dma_irqcl = false;
mmio.sa1_nmicl = false;
//$220c,$220d SNV
mmio.snv = 0x0000;
//$220e,$220f SIV
mmio.siv = 0x0000;
//$2210
mmio.hvselb = false;
mmio.ven = false;
mmio.hen = false;
//$2212,$2213 HCNT
mmio.hcnt = 0x0000;
//$2214,$2215 VCNT
mmio.vcnt = 0x0000;
//$2220-2223 CXB, DXB, EXB, FXB
mmio.cbmode = 0;
mmio.dbmode = 0;
mmio.ebmode = 0;
mmio.fbmode = 0;
mmio.cb = 0x00;
mmio.db = 0x01;
mmio.eb = 0x02;
mmio.fb = 0x03;
//$2224 BMAPS
mmio.sbm = 0x00;
//$2225 BMAP
mmio.sw46 = false;
mmio.cbm = 0x00;
//$2226 SWBE
mmio.swen = false;
//$2227 CWBE
mmio.cwen = false;
//$2228 BWPA
mmio.bwp = 0x0f;
//$2229 SIWP
mmio.siwp = 0x00;
//$222a CIWP
mmio.ciwp = 0x00;
//$2230 DCNT
mmio.dmaen = false;
mmio.dprio = false;
mmio.cden = false;
mmio.cdsel = false;
mmio.dd = 0;
mmio.sd = 0;
//$2231 CDMA
mmio.chdend = false;
mmio.dmasize = 0;
mmio.dmacb = 0;
//$2232-$2234 SDA
mmio.dsa = 0x000000;
//$2235-$2237 DDA
mmio.dda = 0x000000;
//$2238,$2239 DTC
mmio.dtc = 0x0000;
//$223f BBF
mmio.bbf = 0;
//$2240-$224f BRF
for(unsigned i = 0; i < 16; i++) {
mmio.brf[i] = 0x00;
}
//$2250 MCNT
mmio.acm = 0;
mmio.md = 0;
//$2251,$2252 MA
mmio.ma = 0x0000;
//$2253,$2254 MB
mmio.mb = 0x0000;
//$2258 VBD
mmio.hl = false;
mmio.vb = 16;
//$2259-$225b
mmio.va = 0x000000;
mmio.vbit = 0;
//$2300 SFR
mmio.cpu_irqfl = false;
mmio.chdma_irqfl = false;
//$2301 CFR
mmio.sa1_irqfl = false;
mmio.timer_irqfl = false;
mmio.dma_irqfl = false;
mmio.sa1_nmifl = false;
//$2302,$2303 HCR
mmio.hcr = 0x0000;
//$2304,$2305 VCR
mmio.vcr = 0x0000;
//$2306-$230a MR
mmio.mr = 0;
//$230b
mmio.overflow = false;
}
SA1::SA1() {
}
};

35
tools/bsnes/chip/sa1/sa1.hpp Executable file
View File

@@ -0,0 +1,35 @@
#include "bus/bus.hpp"
class SA1 : public CPUcore, public MMIO {
public:
#include "dma/dma.hpp"
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
struct Status {
bool interrupt_pending;
uint16_t interrupt_vector;
uint16_t scanlines;
uint16_t vcounter;
uint16_t hcounter;
} status;
void enter();
void interrupt(uint16_t vector);
void tick();
alwaysinline void trigger_irq();
alwaysinline void last_cycle();
alwaysinline bool interrupt_pending();
void init();
void enable();
void power();
void reset();
SA1();
};
extern SA1 sa1;
extern SA1Bus sa1bus;

View File

@@ -1,8 +1,10 @@
#include <../base.hpp>
#include <../cart/cart.hpp>
#define SDD1_CPP
#include "sdd1.hpp"
#define SDD1_CPP
namespace SNES {
SDD1 sdd1;
#include "sdd1emu.cpp"
void SDD1::init() {}
@@ -11,7 +13,7 @@ void SDD1::enable() {
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
//buffer address and transfer size information for use in SDD1::read()
for(unsigned i = 0x4300; i <= 0x437f; i++) {
cpu_mmio[i & 0x7f] = memory::mmio.get(i);
cpu_mmio[i & 0x7f] = memory::mmio.mmio[i - 0x2000];
memory::mmio.map(i, *this);
}
@@ -156,3 +158,5 @@ SDD1::SDD1() {
SDD1::~SDD1() {
delete[] buffer.data;
}
};

66
tools/bsnes/chip/sgb/sgb.cpp Executable file
View File

@@ -0,0 +1,66 @@
#include <../base.hpp>
#define SGB_CPP
namespace SNES {
SuperGameBoy sgb;
void SuperGameBoy::enter() {
while(true) {
if(sgb_run) {
unsigned samples = sgb_run(samplebuffer, 16);
scheduler.addclocks_cop(samples * 10);
scheduler.sync_copcpu();
} else {
scheduler.addclocks_cop(64 * 1024 * 1024);
scheduler.sync_copcpu();
}
}
}
uint8_t SuperGameBoy::read(unsigned addr) {
addr &= 0xffff;
if(sgb_read) return sgb_read(addr);
return 0x00;
}
void SuperGameBoy::write(unsigned addr, uint8_t data) {
addr &= 0xffff;
if(sgb_write) return sgb_write(addr, data);
}
void SuperGameBoy::init() {
if(libsgb.open("SuperGameBoy")) {
sgb_init = libsgb.sym("sgb_init");
sgb_term = libsgb.sym("sgb_term");
sgb_power = libsgb.sym("sgb_power");
sgb_reset = libsgb.sym("sgb_reset");
sgb_read = libsgb.sym("sgb_read");
sgb_write = libsgb.sym("sgb_write");
sgb_run = libsgb.sym("sgb_run");
}
}
void SuperGameBoy::enable() {
}
void SuperGameBoy::power() {
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
if(sgb_init) {
sgb_init(SGB2,
memory::gbrom.data(), memory::gbrom.size(),
memory::gbram.data(), memory::gbram.size()
);
}
if(sgb_power) sgb_power();
}
void SuperGameBoy::reset() {
if(sgb_reset) sgb_reset();
}
};

28
tools/bsnes/chip/sgb/sgb.hpp Executable file
View File

@@ -0,0 +1,28 @@
class SuperGameBoy : public Memory {
public:
void enter();
uint8_t read(unsigned addr);
void write(unsigned addr, uint8_t data);
void init();
void enable();
void power();
void reset();
private:
library libsgb;
uint32_t samplebuffer[4096];
enum { SGB1 = 0, SGB2 = 1 };
function<bool (bool, uint8_t*, unsigned, uint8_t*, unsigned)> sgb_init;
function<void ()> sgb_term;
function<void ()> sgb_power;
function<void ()> sgb_reset;
function<uint8_t (unsigned)> sgb_read;
function<void (unsigned, uint8_t)> sgb_write;
function<unsigned (uint32_t*, unsigned)> sgb_run;
};
extern SuperGameBoy sgb;

View File

@@ -1,8 +1,10 @@
#include <../base.hpp>
#include <../cart/cart.hpp>
#define SPC7110_CPP
#include "spc7110.hpp"
#define SPC7110_CPP
namespace SNES {
SPC7110 spc7110;
#include "decomp.cpp"
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@@ -670,3 +672,6 @@ void SPC7110::write(unsigned addr, uint8 data) {
SPC7110::SPC7110() {
}
};

View File

@@ -1,6 +1,9 @@
#include <../base.hpp>
#include <../cart/cart.hpp>
#include "srtc.hpp"
#define SRTC_CPP
namespace SNES {
SRTC srtc;
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@@ -224,3 +227,6 @@ void SRTC::mmio_write(unsigned addr, uint8 data) {
SRTC::SRTC() {
}
};

View File

@@ -1,7 +1,10 @@
#include <../base.hpp>
#define ST010_CPP
#include "st010.hpp"
#define ST010_CPP
namespace SNES {
ST010 st010;
#include "st010_data.hpp"
#include "st010_op.cpp"
@@ -85,3 +88,5 @@ void ST010::write(unsigned addr, uint8 data) {
ram[0x0021] &= ~0x80;
}
}
};

View File

@@ -1 +0,0 @@
@mingw32-make platform=win compiler=mingw32-gcc clean

View File

@@ -1 +0,0 @@
make platform=x compiler=gcc clean

3
tools/bsnes/cpu/core/bpp.sh Executable file
View File

@@ -0,0 +1,3 @@
clear
bpp opcode_functions.cpp opcode_functions.bpp
bpp opcode_headers.hpp opcode_headers.bpp

51
tools/bsnes/cpu/core/core.cpp Executable file
View File

@@ -0,0 +1,51 @@
#include <../base.hpp>
#define CPUCORE_CPP
namespace SNES {
#include "opcode_algorithms.cpp"
#include "opcode_functions.cpp"
#include "opcode_tables.cpp"
#include "disasm/disasm.cpp"
//immediate, 2-cycle opcodes with I/O cycle will become bus read
//when an IRQ is to be triggered immediately after opcode completion.
//this affects the following opcodes:
// clc, cld, cli, clv, sec, sed, sei,
// tax, tay, txa, txy, tya, tyx,
// tcd, tcs, tdc, tsc, tsx, txs,
// inc, inx, iny, dec, dex, dey,
// asl, lsr, rol, ror, nop, xce.
alwaysinline void CPUcore::op_io_irq() {
if(interrupt_pending()) {
//modify I/O cycle to bus read cycle, do not increment PC
op_read(regs.pc.d);
} else {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond2() {
if(regs.d.l != 0x00) {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
op_io();
}
}
CPUcore::CPUcore() {
initialize_opcode_table();
}
};

View File

@@ -1,11 +1,25 @@
class CPUcore {
public:
#include "registers.hpp"
#include "memory.hpp"
#include "opcode_headers.hpp"
#include "disasm/disasm.hpp"
regs_t regs;
reg24_t aa, rd;
uint8_t dp, sp;
uint8_t sp, dp;
void op_irq();
virtual void op_io() = 0;
virtual uint8_t op_read(uint32_t addr) = 0;
virtual void op_write(uint32_t addr, uint8_t data) = 0;
virtual void last_cycle() = 0;
virtual bool interrupt_pending() = 0;
inline bool in_opcode() { return status.in_opcode; }
void op_io_irq();
void op_io_cond2();
void op_io_cond4(uint16 x, uint16 y);
void op_io_cond6(uint16 addr);
//op_read
void op_adc_b();
void op_adc_w();
void op_and_b();
@@ -30,7 +44,7 @@
void op_ora_w();
void op_sbc_b();
void op_sbc_w();
//op_rmw
void op_inc_b();
void op_inc_w();
void op_dec_b();
@@ -48,7 +62,18 @@
void op_tsb_b();
void op_tsb_w();
void op_io_irq();
void op_io_cond2();
void op_io_cond4(uint16 x, uint16 y);
void op_io_cond6(uint16 addr);
void (CPUcore::**opcode_table)();
void (CPUcore::*op_table[256 * 5])();
void initialize_opcode_table();
void update_table();
enum {
table_EM = 0, // 8-bit accumulator, 8-bit index (emulation mode)
table_MX = 256, // 8-bit accumulator, 8-bit index
table_Mx = 512, // 8-bit accumulator, 16-bit index
table_mX = 768, //16-bit accumulator, 8-bit index
table_mx = 1024, //16-bit accumulator, 16-bit index
};
CPUcore();
};

Some files were not shown because too many files have changed in this diff Show More