add AtariST emulation

pull/40/head
jean-marcharvengt 2025-02-18 20:49:00 +01:00
rodzic 99ff03ea62
commit fdc2f72477
46 zmienionych plików z 63520 dodań i 847 usunięć

Wyświetl plik

@ -19,8 +19,9 @@ include(pico_sdk_import.cmake)
#set(TARGET picovcs)
#set(TARGET picogb)
#set(TARGET picopce)
set(TARGET picosms)
#set(TARGET picosms)
#set(TARGET picogen)
set(TARGET picocastaway)
#set(TARGET pico5200)
@ -334,6 +335,21 @@ set(PICOGB_SOURCES
)
endif()
if( ${TARGET} MATCHES "picocastaway" )
set(PICOCASTAWAY_SOURCES
picocastaway/emu.cpp
picocastaway/blitter.cpp
picocastaway/famec.cpp
picocastaway/fdc.cpp
picocastaway/ikbd.cpp
picocastaway/m68k_intrf.cpp
picocastaway/mem.cpp
picocastaway/st.cpp
picocastaway/sound.cpp
picocastaway/picocastaway.cpp
)
endif()
if( ${TARGET} MATCHES "testio" )
set(TESTIO_SOURCES
testio/testio.cpp
@ -398,10 +414,11 @@ add_executable(${TARGET}
${PICOPCE_SOURCES}
${PICOGB_SOURCES}
${PICOMSX_SOURCES}
${PICOCASTAWAY_SOURCES}
${TESTIO_SOURCES}
${TESTVGA_SOURCES}
${TESTKEYMAX_SOURCES}
# ${PSRAM_SOURCES}
${PSRAM_SOURCES}
${FLASH_SOURCES}
${DISPLAY_SOURCES}
${FATSD_SOURCES}

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,211 @@
/*
* Castaway
* (C) 1994 - 2002 Martin Doering, Joachim Hoenig
*
* blitter.c - ST blitter chip emulation
*
* This file is distributed under the GPL, version 2 or at your
* option any later version. See doc/license.txt for details.
*
* revision history
* 23.05.2002 JH FAST1.0.1 code import: KR -> ANSI, restructuring
* 09.06.2002 JH Renamed io.c to st.c again (io.h conflicts with system headers)
* 02.10.2002 JH use uint16 etc.
*/
static char sccsid[] = "$Id: blitter.c,v 1.3 2002/10/02 22:44:51 jhoenig Exp $";
#include <stdio.h>
#include "dcastaway.h"
#include "st.h"
#include "mem.h"
#include "m68k_intrf.h"
#define FXSR 0x80
#define NFSR 0x40
#define SKEW 0x0f
#define BUSY 0x80
#define HOG 0x40
#define SMUDGE 0x20
#define LINENO 0x0f
void bitblt(void)
{
uint32 blt_src_in;
uint16 blt_src_out, blt_hop_out, blt_dst_in, blt_dst_out, mask_out;
int xc, yc, lineno, last, first;
#if (VERBOSE & 0x8)
DBG_OUT ("bitblt: Start\n");
DBG_OUT ("HALFT[] 0x%04x-%04x-%04x-%04x\n", (uint16) blt_halftone[0], blt_halftone[1], blt_halftone[2], blt_halftone[3]);
DBG_OUT ("Y COUNT 0x%04x\n", (uint16) blt_y_cnt);
DBG_OUT ("X COUNT 0x%04x\n", (uint16) blt_x_cnt);
DBG_OUT ("X S INC 0x%04x\n", (uint16) blt_src_x_inc);
DBG_OUT ("Y S INC 0x%04x\n", (uint16) blt_src_y_inc);
DBG_OUT ("X D INC 0x%04x\n", (uint16) blt_dst_x_inc);
DBG_OUT ("Y D INC 0x%04x\n", (uint16) blt_dst_y_inc);
DBG_OUT ("ENDMASK 0x%04x-%04x-%04x\n", (uint16) blt_end_1, (uint16) blt_end_2, (uint16) blt_end_3);
DBG_OUT ("S_ADDR 0x%08lx\n", blt_src_addr);
DBG_OUT ("D_ADDR 0x%08lx\n", blt_dst_addr);
DBG_OUT ("HOP=%01d, OP=%02d\n", blt_hop & 0x3, blt_op & 0xf);
DBG_OUT ("HOPline=%02d\n", blt_status & 0xf);
DBG_OUT ("NFSR=%d, FXSR=%d, SKEW=%02d\n", (blt_skew & NFSR) != 0,
(blt_skew & FXSR) != 0,
(blt_skew & SKEW));
#endif
yc = (blt_y_cnt == 0) ? 65536 : blt_y_cnt;
while (yc-- > 0) {
xc = (blt_x_cnt == 0) ? 65536 : blt_x_cnt;
first = 1;
blt_src_in = 0;
/* next line to get rid of obnoxious compiler warnings */
blt_src_out = blt_hop_out = blt_dst_out = 0;
while (xc-- > 0) {
last = (xc == 0);
if ((blt_hop & 0x03) >= 2) {
/* read source into blt_src_in */
if (blt_src_x_inc >= 0) {
if (first && (blt_skew & FXSR)) {
blt_src_in = (GetMemW (blt_src_addr) << 16);
blt_src_addr += blt_src_x_inc;
} else {
blt_src_in <<= 16;
}
if (last && (blt_skew & NFSR)) {
blt_src_addr -= blt_src_x_inc;
} else {
blt_src_in |= (uint16) GetMemW (blt_src_addr);
if (!last) {
blt_src_addr += blt_src_x_inc;
}
}
} else {
if (first && (blt_skew & FXSR)) {
blt_src_in = (uint16) GetMemW (blt_src_addr);
blt_src_addr +=blt_src_x_inc;
} else {
blt_src_in >>= 16;
}
if (last && (blt_skew & NFSR)) {
blt_src_addr -= blt_src_x_inc;
} else {
blt_src_in |= (GetMemW (blt_src_addr) << 16);
if (!last) {
blt_src_addr += blt_src_x_inc;
}
}
}
/* shift blt_skew times into blt_src_out */
blt_src_out = blt_src_in >> (blt_skew & SKEW);
#if (VERBOSE & 0x8)
DBG_OUT ("%04x ", blt_src_out);
#endif
}
/* halftone OP */
lineno = ((blt_status & SMUDGE) ? blt_src_out : blt_status) & LINENO;
switch (blt_hop & 0x3) {
case 0:
blt_hop_out = 0xffff;
break;
case 1:
blt_hop_out = blt_halftone[lineno];
break;
case 2:
blt_hop_out = blt_src_out;
break;
case 3:
blt_hop_out = blt_src_out & blt_halftone[lineno];
break;
}
/* read destination into blt_dst_in */
blt_dst_in = GetMemW (blt_dst_addr);
/* op into blt_dst_out */
switch (blt_op & 0xf) {
case 0:
blt_dst_out = 0;
break;
case 1:
blt_dst_out = blt_hop_out & blt_dst_in;
break;
case 2:
blt_dst_out = blt_hop_out & ~blt_dst_in;
break;
case 3:
blt_dst_out = blt_hop_out;
break;
case 4:
blt_dst_out = ~blt_hop_out & blt_dst_in;
break;
case 5:
blt_dst_out = blt_dst_in;
break;
case 6:
blt_dst_out = blt_hop_out ^ blt_dst_in;
break;
case 7:
blt_dst_out = blt_hop_out | blt_dst_in;
break;
case 8:
blt_dst_out = ~blt_hop_out & ~blt_dst_in;
break;
case 9:
blt_dst_out = ~blt_hop_out ^ blt_dst_in;
break;
case 0xa:
blt_dst_out = ~blt_dst_in;
break;
case 0xb:
blt_dst_out = blt_hop_out | ~blt_dst_in;
break;
case 0xc:
blt_dst_out = ~blt_hop_out;
break;
case 0xd:
blt_dst_out = ~blt_hop_out | blt_dst_in;
break;
case 0xe:
blt_dst_out = ~blt_hop_out | ~blt_dst_in;
break;
case 0xf:
blt_dst_out = 0xffff;
break;
}
/* and endmask */
if (first) {
mask_out = (blt_dst_out & blt_end_1) | (blt_dst_in & ~blt_end_1);
} else if (last) {
mask_out = (blt_dst_out & blt_end_3) | (blt_dst_in & ~blt_end_3);
} else {
mask_out = (blt_dst_out & blt_end_2) | (blt_dst_in & ~blt_end_2);
}
SetMemW (blt_dst_addr, mask_out);
if (!last) {
blt_dst_addr += blt_dst_x_inc;
}
first = 0;
}
#if (VERBOSE & 0x8)
DBG_OUT ("\n");
#endif
blt_status = (blt_status + ((blt_dst_y_inc >= 0) ? 1 : 15)) & 0xef;
blt_src_addr += blt_src_y_inc;
blt_dst_addr += blt_dst_y_inc;
}
/* blt_status &= ~BUSY; */
blt_y_cnt = 0;
#if (VERBOSE & 0x8)
DBG_OUT ("bitblt: End\n");
DBG_OUT ("HALFT[] 0x%04x-%04x-%04x-%04x\n", (uint16) blt_halftone[0], blt_halftone[1], blt_halftone[2], blt_halftone[3]);
DBG_OUT ("Y COUNT 0x%04x\n", (uint16) blt_y_cnt);
DBG_OUT ("X COUNT 0x%04x\n", (uint16) blt_x_cnt);
DBG_OUT ("X S INC 0x%04x\n", (uint16) blt_src_x_inc);
DBG_OUT ("Y S INC 0x%04x\n", (uint16) blt_src_y_inc);
DBG_OUT ("X D INC 0x%04x\n", (uint16) blt_dst_x_inc);
DBG_OUT ("Y D INC 0x%04x\n", (uint16) blt_dst_y_inc);
DBG_OUT ("ENDMASK 0x%04x-%04x-%04x\n", (uint16) blt_end_1, (uint16) blt_end_2, (uint16) blt_end_3);
DBG_OUT ("S_ADDR 0x%08lx\n", blt_src_addr);
DBG_OUT ("D_ADDR 0x%08lx\n", blt_dst_addr);
DBG_OUT ("HOP=%01d, OP=%02d\n", blt_hop & 0x3, blt_op & 0xf);
DBG_OUT ("HOPline=%02d\n", blt_status & 0xf);
DBG_OUT ("NFSR=%d, FXSR=%d, SKEW=%02d\n", (blt_skew & NFSR) != 0,
(blt_skew & FXSR) != 0,
(blt_skew & SKEW));
#endif
}

Wyświetl plik

@ -0,0 +1,138 @@
#define USE_FAME_CORE_C 1
#define USE_FAME_CORE 1
#define FAME_GLOBAL_CONTEXT 1
//#define NO_SOUND 1
#ifndef CONFIGH
#define CONFIGH
/*
* Environment Configuration
*/
#if !defined(USE_BIG_ENDIAN) && !defined(USE_LITTLE_ENDIAN)
#define USE_LITTLE_ENDIAN
#endif
#ifndef INLINE
#define INLINE static __inline__
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* compiler representation of M68000 .B .W .L operands
*/
#ifndef __cplusplus
typedef signed char bool;
#endif
#ifndef DREAMCAST
typedef signed char int8;
typedef signed short int16;
typedef signed long int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
#else
#include <kos.h>
#endif
/*
* Atari ST emulator defaults
*/
#define CARBASE 0x00fa0000L
#define CARSIZE 0x00020000L /* 128k cartridge */
#define ROMBASE 0x00fc0000L
#define ROMBASE2 0x00e00000L
#define ROMSIZE 0x00030000L /* 192k */
#define ROMSIZE2 0x00040000L /* 256k */
#define IOBASE 0x00ff8000L
#define IOSIZE 0x00008000L /* 32k */
#define SVADDR 0x00000800L
#define MONITOR 2 /* 0=color 320x200 or 2=monochrome 640x400 */
#define SIDES 2 /* disk sides */
#define TRACKS 80 /* tracks on disk */
#define SECTORS 9 /* sectors per track */
#define SECSIZE 512 /* byte per sector */
#define TIMER 0 /* 0=normal (200Hz), 2=slow (100Hz) */
#define NO_BLITTER
#define NO_RTC /* Do not emulate Real-Time-Clock */
//#define CHKADDRESSERR /* if set, unaligned access will raise an address
// error (slower, but expected behaviour) */
//#define CHKTRACE /* if set, the trace bit works (slower). */
//#define NATFEAT /* if set, native features are supported */
#undef DEBUG /* Debug */
#undef DISASS
#undef DBGTRACE
#undef DETECT_PREFETCH
/*
* Debug options
*/
#ifdef DEBUG
#ifndef CHKADDRESSERR
#define CHKADDRESSERR /* force address error checking */
#endif
#define VERBOSE 0x1 /* ~INT, IO, ~BLITTER */
#define TRACEBACK 2000 /* 68k traceback buffer size */
#undef INTERNALTRACE /* trace 68k operation internal execution */
#define DBG_OUT if (verb_on) printf
#define DBG_STOP if (stop_on) Stop
#define NO_TIMER
/* special DEBUG action on traps */
#define ON_TRAP(number) if (number == 33) {stop_on++;};
/* special DEBUG action on R/W access to an unmapped address */
#define ON_UNMAPPED(address, value)
/* special DEBUG action on unmapped I/O access */
#define ON_NOIO(offset, value)
/* special DEBUG action on write access */
#define ON_WRITE(address, value)
extern int trace_on;
extern int stop_on;
extern int verb_on;
extern void SaveState(unsigned short inst);
extern void Stop(void);
#else /* not DEBUG */
#define ON_TRAP(number)
#define ON_UNMAPPED(address, value)
#define ON_NOIO(address, value)
#define ON_WRITE(address, value)
// # define ON_TRAP(number) if (number == 33 && GetMemW(areg[7]) == 0x4c) { TraceStop(); }
#endif
#endif
#ifdef DEBUG_FAME_FFLUSH
#undef DEBUG_FAME_FFLUSH
#define DEBUG_FAME_FFLUSH fflush(stdout)
#else
#define DEBUG_FAME_FFLUSH
#endif
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
extern uint8 ram_readb(int address);
extern void ram_writeb(int address, uint8 val);
extern int emulating;
extern int nScreenRefreshRate;
extern int draw_border, maybe_border;
extern unsigned screen_pitch, screen_width, screen_height;
extern unsigned cyclenext;
extern unsigned vid_adr_cycleyet;
extern unsigned char *vid_cycle;

Wyświetl plik

@ -0,0 +1,9 @@
#ifndef DISKAPI_H
#define DISKAPI_H
int disk_Size(char * filename);
int disk_Open(char * filename);
int disk_Read(unsigned char * buf, int size);
int disk_Seek(int seek);
#endif

Wyświetl plik

@ -0,0 +1,883 @@
#include <string.h>
#include "emuapi.h"
#include "kbd.h"
#include "dcastaway.h"
#include "st.h"
#include "mem.h"
#include "m68k_intrf.h"
#include "iopins.h"
#ifndef NO_SOUND
#include "sound.h"
#endif
#include "tossw12.h"
#ifdef HAS_PSRAM
#include "psram_t.h"
PSRAM_T psram = PSRAM_T(PSRAM_CS, PSRAM_MOSI, PSRAM_SCLK, PSRAM_MISO);
#endif
//#define PSRAM_DISK 1
#ifdef ALL_IN_RAM
uint8 *mem1base;
#else
#ifdef PSRAM_FAKE
uint8 *mem1base;
#endif
#endif
uint8 *mem2base;
uint8 *rombase;
int hbl = 0;
int end_visible_screen = 264;
int hsync = 0;
int vsyncpend = 0, hsyncpend = 0;
int exmousex=160,exmousey=100,MouseRelease1=0,MouseRelease2=0;
int CompleteSndBufIdx;
int waitstate=0;
int dcastaway_disc_writed[2] = { 0 , 0 };
int dcastaway_disc_for_write[2] = { 0 , 0 };
int draw_border=0, maybe_border=0;
unsigned cyclenext=512;
unsigned vid_adr_cycleyet=0;
static unsigned char vid_cycles_pal[1024];
static unsigned char vid_cycles_ntsc[1024];
unsigned char *vid_cycle=(unsigned char *)&vid_cycles_pal;
int readdsk=1;
extern unsigned char fdc_motor;
#define XRES 320
#define YRES 200
static unsigned short line[XRES];
#define PALMULT8(x) ((x)<<5)
#define RGBVAL16(r,g,b) ( (((r>>3)&0x1f)<<11) | (((g>>2)&0x3f)<<5) | (((b>>3)&0x1f)<<0) )
void Redraw16 ( int row, int vid_adr ) {
static unsigned short palmap [ 16 ];
//Source address
register unsigned long line_i=vid_adr;
register unsigned short *line_o= &line[0];
//Build paletter
if (vid_flag) {
unsigned char i, r, g, b;
for (i = 0; i < 16; i++) {
b = PALMULT8 ( (vid_col[i] & 0x7) );
g = PALMULT8 ( ((vid_col[i] >> 4) & 0x7) );
r = PALMULT8 ( ((vid_col[i] >> 8) & 0x7) );
palmap [ i ] = RGBVAL16(r,g,b);
}
vid_flag=0;
}
register int col;
register int bit;
for (col=0; col<20; col++) {
register unsigned short pl0=ReadW(line_i),pl1=ReadW(line_i+2),pl2=ReadW(line_i+4),pl3=ReadW(line_i+6);
line_i += 8;
for (bit=15;bit>=0;bit--) {
int ind = (pl0 >> bit) & 0x1;
ind += ((pl1 >> bit) & 0x1)<<1;
ind += ((pl2 >> bit) & 0x1)<<2;
ind += ((pl3 >> bit) & 0x1)<<3;
*line_o++ = palmap [ ind ];
}
}
emu_DrawLine16(&line[0], XRES, YRES, row);
}
void Redraw16_med ( int row, int vid_adr ) {
static unsigned short palmap [ 4 ];
//Source address
register unsigned long line_i=vid_adr;
register unsigned short *line_o= &line[0];
//Build paletter
if (vid_flag) {
unsigned char i, r, g, b;
for (i = 0; i < 4; i++) {
b = PALMULT8 ( (vid_col[i] & 0x7) );
g = PALMULT8 ( ((vid_col[i] >> 4) & 0x7) );
r = PALMULT8 ( ((vid_col[i] >> 8) & 0x7) );
palmap [ i ] = RGBVAL16(r,g,b);
}
vid_flag=0;
}
register int col;
register int bit;
for (col=0; col<40; col++) {
register unsigned short pl0=ReadW(line_i),pl1=ReadW(line_i+2);
line_i += 4;
for (bit=15;bit>=0;bit--) {
int ind = (pl0 >> bit) & 0x1;
ind += ((pl1 >> bit) & 0x1)<<1;
if (bit & 0x01)
*line_o++ = palmap [ ind ];
}
}
emu_DrawLine16(&line[0], XRES, YRES, row);
}
static uint8 disk0[256];
static uint8 disk1[256];
void ast_Init(void)
{
#ifdef HAS_PSRAM
psram.begin();
#endif
emu_printf("Allocating RAM");
#ifdef ALL_IN_RAM
mem1base = (uint8*) malloc(MEMSIZE);
if (!mem1base) emu_printf("malloc mem1 failed\n");
mem2base = &mem1base[RAM1SIZE];
#else
if ((MEMSIZE-RAM1SIZE)>0) {
mem2base = (uint8*) malloc(MEMSIZE-RAM1SIZE);
if (!mem2base) emu_printf("malloc mem2 failed\n");
}
#ifdef PSRAM_FAKE
if ((RAM1SIZE)>0) {
mem1base = (uint8*) malloc(RAM1SIZE);
if (!mem1base) emu_printf("malloc mem1 failed\n");
}
else {
mem1base = mem2base;
}
#endif
#endif
rombase = (uint8*)&tos[0]-ROMBASE;
#ifdef ALL_IN_RAM
memcpy (mem1base, &tos[0], 8);
#else
//for (int i=0; i<MEMSIZE;i++)
// WriteBB(i, 0);
for (int i=0; i<8;i++)
WriteBB(i, tos[i]);
#endif
extern unsigned char *disc[2];
disc [ 0 ] = (uint8*) &disk0[0];
disc [ 1 ] = (uint8*) &disk1[0];
}
#define INV_KEY 0
const int16_t keyboardAsciiConv[] = // QWERTY Keyboard
{
/* 0x00 */ INV_KEY,
/* 0x01 */ INV_KEY,
/* 0x02 */ INV_KEY,
/* 0x03 */ INV_KEY,
/* 0x04 */ INV_KEY,
/* 0x05 */ INV_KEY,
/* 0x06 */ INV_KEY,
/* 0x07 */ INV_KEY,
/* 0x08 */ INV_KEY,
/* 0x09 */ 0x0f, // tab
/* 0x0A */ 0x1C, // enter
/* 0x0B */ INV_KEY,
/* 0x0C */ 0x1C, // enter
/* 0x0D */ 0x1C, // enter
/* 0x0E */ INV_KEY,
/* 0x0F */ INV_KEY,
/* 0x10 */ INV_KEY,
/* 0x11 */ INV_KEY,
/* 0x12 */ INV_KEY,
/* 0x13 */ INV_KEY,
/* 0x14 */ INV_KEY,
/* 0x15 */ INV_KEY,
/* 0x16 */ INV_KEY,
/* 0x17 */ INV_KEY,
/* 0x18 */ INV_KEY,
/* 0x19 */ INV_KEY,
/* 0x1A */ INV_KEY,
/* 0x1B */ 0x01, // esc
/* 0x1C */ INV_KEY,
/* 0x1D */ INV_KEY,
/* 0x1E */ INV_KEY,
/* 0x1F */ INV_KEY,
/* 0x20 */ 0x39, // space
/* 0x21 */ INV_KEY,
/* 0x22 */ INV_KEY,
/* 0x23 */ INV_KEY,
/* 0x24 */ INV_KEY,
/* 0x25 */ INV_KEY,
/* 0x26 */ 43, // ampercent (backslash)
/* 0x27 */ 40, // single quote
/* 0x28 */ 26, // bracket left
/* 0x29 */ 27, // bracket right
/* 0x2A */ INV_KEY, // mult *
/* 0x2B */ INV_KEY,
/* 0x2C */ 51, // comma ,
/* 0x2D */ 12, // minus -
/* 0x2E */ 52, // period .
/* 0x2F */ 53, // slash /
/* 0x30 */ 0x0B, // 0
/* 0x31 */ 0x02,
/* 0x32 */ 0x03,
/* 0x33 */ 0x04,
/* 0x34 */ 0x05,
/* 0x35 */ 0x06,
/* 0x36 */ 0x07,
/* 0x37 */ 0x08,
/* 0x38 */ 0x09,
/* 0x39 */ 0x0A, // 9
/* 0x3A */ INV_KEY, // colon :
/* 0x3B */ 39, // semi colon ;
/* 0x3C */ INV_KEY,
/* 0x3D */ 13, // equal =
/* 0x3E */ INV_KEY,
/* 0x3F */ INV_KEY,
/* 0x40 */ INV_KEY,
/* 0x41 */ INV_KEY,
/* 0x42 */ INV_KEY,
/* 0x43 */ INV_KEY,
/* 0x44 */ INV_KEY,
/* 0x45 */ INV_KEY,
/* 0x46 */ INV_KEY,
/* 0x47 */ INV_KEY,
/* 0x48 */ INV_KEY,
/* 0x49 */ INV_KEY,
/* 0x4A */ INV_KEY,
/* 0x4B */ INV_KEY,
/* 0x4C */ INV_KEY,
/* 0x4D */ INV_KEY,
/* 0x4E */ INV_KEY,
/* 0x4F */ INV_KEY,
/* 0x50 */ INV_KEY,
/* 0x51 */ INV_KEY,
/* 0x52 */ INV_KEY,
/* 0x53 */ INV_KEY,
/* 0x54 */ INV_KEY,
/* 0x55 */ INV_KEY,
/* 0x56 */ INV_KEY,
/* 0x57 */ INV_KEY,
/* 0x58 */ INV_KEY,
/* 0x59 */ INV_KEY,
/* 0x5A */ INV_KEY,
/* 0x5B */ INV_KEY,
/* 0x5C */ INV_KEY,
/* 0x5D */ INV_KEY,
/* 0x5E */ INV_KEY,
/* 0x5F */ INV_KEY,
/* 0x60 */ INV_KEY,
/* 0x61 */ 0x1E, // A
/* 0x62 */ 0x30, // B
/* 0x63 */ 0x2E, // C
/* 0x64 */ 0x20, // D
/* 0x65 */ 0x12, // E
/* 0x66 */ 0x21, // F
/* 0x67 */ 0x22, // G
/* 0x68 */ 0x23, // H
/* 0x69 */ 0x17, // I
/* 0x6A */ 0x24, // J
/* 0x6B */ 0x25, // K
/* 0x6C */ 0x26, // L
/* 0x6D */ 0x32, // M
/* 0x6E */ 0x31, // N
/* 0x6F */ 0x18, // O
/* 0x70 */ 0x19, // P
/* 0x71 */ 0x10, // Q
/* 0x72 */ 0x13, // R
/* 0x73 */ 0x1F, // S
/* 0x74 */ 0x14, // T
/* 0x75 */ 0x16, // U
/* 0x76 */ 0x2F, // V
/* 0x77 */ 0x11, // W
/* 0x78 */ 0x2D, // X
/* 0x79 */ 0x2C, // Y
/* 0x7A */ 0x15, // Z
/* 0x7B */ INV_KEY,
/* 0x7C */ INV_KEY,
/* 0x7D */ INV_KEY,
/* 0x7E */ INV_KEY,
/* 0x7F */ 0x0E // backspace
};
const int16_t keyboardSpecialConv[] = // Functions and other keys
{
/* 0xC0 */ INV_KEY,
/* 0xC1 */ INV_KEY,
/* 0xC2 */ 0x3b, // F1
/* 0xC3 */ 0x3c, // F2
/* 0xC4 */ 0x3d, // F3
/* 0xC5 */ 0x3e, // F4
/* 0xC6 */ 0x3f, // F5
/* 0xC7 */ 0x40, // F6
/* 0xC8 */ 0x41, // F7
/* 0xC9 */ 0x42, // F8
/* 0xCA */ 0x43, // F9
/* 0xCB */ 0x44, // F10
/* 0xCC */ INV_KEY,
/* 0xCD */ INV_KEY,
/* 0xCE */ INV_KEY,
/* 0xCF */ INV_KEY,
/* 0xD0 */ INV_KEY,
/* 0xD1 */ INV_KEY,
/* 0xD2 */ INV_KEY,
/* 0xD3 */ INV_KEY,
/* 0xD4 */ INV_KEY, // DEL
/* 0xD5 */ INV_KEY,
/* 0xD6 */ INV_KEY,
/* 0xD7 */ INV_KEY,
/* 0xD8 */ INV_KEY,
/* 0xD9 */ INV_KEY,
/* 0xDA */ INV_KEY,
/* 0xDB */ INV_KEY,
/* 0xDC */ INV_KEY,
/* 0xDD */ INV_KEY,
/* 0xDE */ INV_KEY,
/* 0xDF */ INV_KEY
};
static int mouse_x = XRES/2;
static int mouse_y = 100;
static int prev_key = 0;
static int prev_j = 0;
static int prev_mouseb = 0;
static bool isMouse = true;
static int joynum = 1;
static int hk = 0;
static int prev_hk = 0;
static int k = 0;
static int prev_k = 0;
void emu_KeyboardOnDown(int keymodifer, int key) {
int keyCode = INV_KEY;
if ( (key >= KBD_KEY_F1) && (key <= KBD_KEY_F10) ) keyCode = (key - KBD_KEY_F1) + 0x3b;
// Specific keys
//153,151,150,152,0x7F 31 //U L R D DEL ESC
//else if (key == KBD_KEY_UP) keyCode = 0x99; // 153
//else if (key == KBD_KEY_LEFT) keyCode = 0x97; // 151
//else if (key == KBD_KEY_DOWN) keyCode = 0x98; // 152
//else if (key == KBD_KEY_RIGHT) keyCode = 0x96; // 150
//else if (key == KBD_KEY_BS) keyCode = 0x7F; // 127
//else if (key == KBD_KEY_ESC) keyCode = 0x1F; // 31
else
keyCode = keyboardAsciiConv[key & 0x7f];
IkbdKeyPress ( keyCode );
}
void emu_KeyboardOnUp(int keymodifer, int key) {
int keyCode = INV_KEY;
if ( (key >= KBD_KEY_F1) && (key <= KBD_KEY_F10) ) keyCode = (key - KBD_KEY_F1) + 0x3b;
// Specific keys
//153,151,150,152,0x7F 31 //U L R D DEL ESC
//else if (key == KBD_KEY_UP) keyCode = 0x99; // 153
//else if (key == KBD_KEY_LEFT) keyCode = 0x97; // 151
//else if (key == KBD_KEY_DOWN) keyCode = 0x98; // 152
//else if (key == KBD_KEY_RIGHT) keyCode = 0x96; // 150
//else if (key == KBD_KEY_BS) keyCode = 0x7F; // 127
//else if (key == KBD_KEY_ESC) keyCode = 0x1F; // 31
else
keyCode = keyboardAsciiConv[key & 0x7f];
IkbdKeyRelease ( keyCode );
}
extern void ast_Input(int click) {
hk = emu_ReadI2CKeyboard();
k = emu_ReadKeys();
}
static void do_events(void)
{
int bClick = k & ~prev_k;
prev_k = k;
// Toggle mouse/joystick
if (bClick & MASK_KEY_USER1) {
if (isMouse) isMouse = false;
else isMouse = true;
}
if (!isMouse)
{
int j = 0;
if (( k & MASK_JOY1_RIGHT) || ( k & MASK_JOY2_RIGHT)) {
j |= 0x04;
}
if (( k & MASK_JOY1_LEFT) || ( k & MASK_JOY2_LEFT)) {
j |= 0x08;
}
if (( k & MASK_JOY1_UP) || ( k & MASK_JOY2_UP)) {
j |= 0x01;
}
if (( k & MASK_JOY1_DOWN) || ( k & MASK_JOY2_DOWN)) {
j |= 0x02;
}
if ( k & MASK_JOY2_BTN) {
j |= 0x80;
}
if (j != prev_j) {
IkbdJoystickChange(joynum,j);
prev_j = j;
}
}
else {
if (( k & MASK_JOY1_LEFT) || ( k & MASK_JOY2_LEFT)) {
if ( mouse_x < XRES ) {
mouse_x += 2;
//Serial.print("r");
IkbdMouseMotion ( mouse_x, mouse_y );
IkbdLoop();
}
}
else if (( k & MASK_JOY1_RIGHT) || ( k & MASK_JOY2_RIGHT)) {
if ( mouse_x > 1 ) {
mouse_x -= 2;
//Serial.print("l");
IkbdMouseMotion ( mouse_x, mouse_y );
IkbdLoop();
}
}
else if (( k & MASK_JOY1_UP) || ( k & MASK_JOY2_UP)) {
if ( mouse_y > 1 ) {
mouse_y -= 2;
//Serial.print("u");
IkbdMouseMotion ( mouse_x, mouse_y );
IkbdLoop();
}
}
else if (( k & MASK_JOY1_DOWN) || ( k & MASK_JOY2_DOWN)) {
if ( mouse_y < YRES ) {
mouse_y += 2;
//Serial.print("d");
IkbdMouseMotion ( mouse_x, mouse_y );
IkbdLoop();
}
}
int mouseb=0;
if ( ( k & MASK_JOY2_BTN) ){
mouseb=1;
}
if ( (mouseb != prev_mouseb) ){
if (mouseb) IkbdMousePress(2);
else IkbdMouseRelease(2);
//Serial.println("btoggle");
IkbdLoop();
prev_mouseb = mouseb;
}
}
}
void ast_Step(void)
{
int delay_fdc_motor=0;
unsigned long cycleco=0;
unsigned long oldpend,newpend;
hsync=0;
hbl=0;
vsyncpend=0;
hsyncpend=0;
int running = 1;
/* Event loop */
while (running)
{
cycleco=cpu_loop(cyclenext);
cycleco+=waitstate;
waitstate=0;
#ifndef NO_SOUND
SoundCycles+=cycleco;
#endif
//MFP timer A delay mode
if (mfp_ascale>1) {
mfp_acount-=mfp_ascale*cycleco;
if (mfp_acount<=0) {
do {mfp_acount+=mfp_tadr;} while (mfp_acount<=0);
oldpend=mfp_ipra; newpend=(oldpend|0x20)&mfp_iera;
if (newpend!=oldpend) {mfp_ipra=newpend;
}
}
#ifdef USE_SHORT_SLICE
cyclenext=4+(mfp_acount/mfp_ascale);
#endif
}
#ifdef USE_SHORT_SLICE
else
cyclenext=512;
#endif
//MFP timer B delay mode
if (mfp_bscale>1) {
mfp_bcount-=mfp_bscale*cycleco;
if (mfp_bcount<=0) {
do {mfp_bcount+=mfp_tbdr;} while (mfp_bcount<=0);
oldpend=mfp_ipra; newpend=(oldpend|0x1)&mfp_iera;
if (newpend!=oldpend) {mfp_ipra=newpend;
}
}
#ifdef USE_SHORT_SLICE
{
int n=4+(mfp_bcount/mfp_bscale);
if (n<cyclenext)
cyclenext=n;
}
#endif
}
//MFP timer C delay mode
if (mfp_cscale>1) {
mfp_ccount-=mfp_cscale*cycleco;
if (mfp_ccount<=0) {
do {mfp_ccount+=mfp_tcdr;} while (mfp_ccount<=0);
oldpend=mfp_iprb; newpend=(oldpend|0x20)&mfp_ierb;
if (newpend!=oldpend) {mfp_iprb=newpend;
}
}
#ifdef USE_SHORT_SLICE
{
int n=4+(mfp_ccount/mfp_cscale);
if (n<cyclenext)
cyclenext=n;
}
#endif
}
//MFP timer D delay mode
if (mfp_dscale>1) {
mfp_dcount-=mfp_dscale*cycleco;
if (mfp_dcount<=0) {
do {mfp_dcount+=mfp_tddr;} while (mfp_dcount<=0);
oldpend=mfp_iprb; newpend=(oldpend|0x10)&mfp_ierb;
if (newpend!=oldpend) {mfp_iprb=newpend;
}
}
#ifdef USE_SHORT_SLICE
{
int n=4+(mfp_dcount/mfp_dscale);
if (n<cyclenext)
cyclenext=n;
}
#endif
}
vid_adr+=(cycleco)&(~3);
//Count hbls
hsync-=cycleco;
if (hsync<=0) {
hbl++; hsync+=512;
//Generate hbl interrupt
Interrupt(AUTOINT2, 2);
//Trigger event counters for visible scan-lines
if (hbl<64) {
vid_adr=(vid_baseh<<16)+(vid_basem<<8);
}
else if (hbl<264) {
if ( (hbl == 132 )) {
// if ( (hbl % (end_visible_screen/2) ) == 0) {
//CPUEvent();
//timer_tick = 1;
}
//Do IO every 64 hbls
if (!(hbl&63)) {
//Generate FDC interrupt in mfp?
if (!(mfp_gpip & 0x20)) {
mfp_iprb |= 0x80;
mfp_iprb &= mfp_ierb;
}
//Generate ACIA interrupt in mfp?
IkbdWriteBuffer();
if (!(mfp_gpip & 0x10)) {
mfp_iprb |= 0x40;
mfp_iprb &= mfp_ierb;
}
}
{ // fremeskip
//Update video address
vid_adr=(vid_baseh<<16)+(vid_basem<<8)+(hbl-64)*160;
//Draw screen line
if (vid_shiftmode==COL2) {
Redraw16_med ( hbl - 64, vid_adr );
} else {
Redraw16 ( hbl - 64, vid_adr );
}
}
//Timer-A event count mode
if (mfp_ascale==1) {
mfp_acount-=1048576;
if (mfp_acount<=0) {
mfp_acount=mfp_tadr;
oldpend=mfp_ipra; newpend=(oldpend|0x20)&mfp_iera;
if (newpend!=oldpend) {mfp_ipra=newpend;
}
}
}
//Timer-B event count mode
if (mfp_bscale==1) {
mfp_bcount-=1048576;
if (mfp_bcount<=0) {
mfp_bcount=mfp_tbdr;
oldpend=mfp_ipra; newpend=(oldpend|0x1)&mfp_iera;
if (newpend!=oldpend) {mfp_ipra=newpend;
}
}
}
}
//Vertical blank?
else if (hbl>=313)
{
//delay(15);
//emu_DrawVsync();
do_events();
#ifndef NO_SOUND
Sound_Update_VBL();
#endif
running=0;
hbl=0;
//Generate vsync interrupt
Interrupt(AUTOINT4, 4);
//Do fdc spinup
if (fdc_motor){
if (delay_fdc_motor>150) {
fdc_status &= ~0x80;
delay_fdc_motor=0;
fdc_motor=0;
}
else delay_fdc_motor++;
}
}
}
//Recalculate interrupts?
{
int mfp_int;
mfp_int=0;
if (6>GetI()) {
//Mfp interrupt
{
int n, number;
uint16 imr, ipr, isr, irr;
int in_request;
//Find in_request and in_service
imr = (mfp_imra<<8)+mfp_imrb;
ipr = (mfp_ipra<<8)+mfp_iprb;
irr = imr & ipr;
isr = (mfp_isra<<8) + mfp_isrb;
//in_request higher than in_service?
if (irr>isr) {
//Find highest set bit
for (in_request = 15; in_request > 0; in_request--) {
if (irr & 0x8000) break;
irr <<= 1;
}
isr = 1 << in_request;
//Set interrupt in service bits in MFP
if (mfp_ivr & 0x8) {
mfp_isra |= isr >> 8;
mfp_isrb |= isr;
}else{
mfp_isra &= (~isr) >> 8;
mfp_isrb &= ~isr;
}
//Clear interrupt pending bits in MFP
mfp_ipra &= ~(isr >> 8);
mfp_iprb &= ~isr;
//Pass interrupt to cpu
number = in_request | (mfp_ivr & 0xf0);
Interrupt(number, 6);
mfp_int=1;
}
}
}
}
}
}
#ifdef HAS_PSRAM
unsigned char ram_readb(int address) {
#ifdef PSRAM_FAKE
return mem1base[address];
#else
return (psram.psread(address));
#endif
}
void ram_writeb(int address, unsigned char val) {
#ifdef PSRAM_FAKE
mem1base[address] = val;
#else
psram.pswrite(address,val);
#endif
}
unsigned short ram_readw(int address) {
#ifdef PSRAM_FAKE
return mem1base[address]|(mem1base[address+1]<<8);
#else
// return psram.psread(address)|(psram.psread(address+1)<<8);
return psram.psread_w(address);
#endif
}
void ram_writew(int address, unsigned short val) {
#ifdef PSRAM_FAKE
mem1base[address] = val;
mem1base[address+1] = val>>8;
#else
psram.pswrite_w(address,val);
#endif
}
#define PSRAM_DISK_OFFSET (2*1024*1024)
// disk IO mapped to PSRAM
static uint8 read_disk(int address) {
return (psram.psread(address+PSRAM_DISK_OFFSET));
}
static void write_disk(int address, uint8 val) {
psram.pswrite(address+PSRAM_DISK_OFFSET,val);
}
#endif
#ifdef PSRAM_DISK
#ifdef HAS_PSRAM
static int disksize = 0;
static int diskpt = 0;
int disk_Size(char * filename) {
//emu_printf("disk size");
//emu_printi(disksize);
return disksize;
}
int disk_Open(char * filename) {
//emu_printf("disk reset pt");
diskpt = 0;
return 1;
}
int disk_Read(unsigned char * buf, int size) {
//emu_printf("disk read");
//emu_printi(size);
int i = 0;
while ( ( i < size) && (diskpt < disksize) ) {
buf[i++] = read_disk(diskpt++);
}
return i;
}
int disk_Seek(int seek) {
//emu_printf("disk seek");
//emu_printi(seek);
diskpt = seek;
return diskpt;
}
#endif
#else
// disk IO mapped to File
static int fd;
int disk_Size(char * filename) {
return emu_FileSize(filename);
}
int disk_Open(char * filename) {
fd = emu_FileOpen(filename,"r+b");
return fd;
}
int disk_Read(unsigned char * buf, int size) {
return emu_FileRead(buf, size, fd);
}
int disk_Seek(int seek) {
return emu_FileSeek(fd,seek,0);
}
#endif
void ast_Start(char * filename)
{
emu_printf("init started");
strncpy (disk[0].name, filename, sizeof(disk[0].name));
#ifdef PSRAM_DISK
#ifdef HAS_PSRAM
char iobuf[512];
int iopos = 0;
disksize = 0;
int n;
int f;
if (f = emu_FileOpen(filename, "r+b")) {
while ( (n = emu_FileRead(&iobuf[0],sizeof(iobuf), f) ) ) {
disksize += n;
for (int i=0; i<n; i++) {
write_disk(iopos++,iobuf[i]);
}
}
emu_FileClose(f);
}
emu_printf("psram loaded");
#endif
#endif
initialize_memmap();
FDCInit(0);
//FDCeject(0);
FDCeject(1);
IkbdReset();
IOInit();
#ifdef HAS_SND
emu_sndInit();
#endif
#ifndef NO_SOUND
Sound_Init();
#endif
HWReset(); /* CPU Reset */
emu_printf("init done");
}
void SND_Process(void *stream, int len) {
#ifndef NO_SOUND
Sound_UpdateFromCallBack16((short *)stream, len);
#endif
}

Wyświetl plik

@ -0,0 +1,5 @@
extern void ast_Init(void);
extern void ast_Step(void);
extern void ast_Start(char * filename);
extern void ast_Input(int click);

Wyświetl plik

@ -0,0 +1,103 @@
#ifndef EMUCFG_H
#define EMUCFG_H
#define PALETTE_SIZE 256
#define VID_FRAME_SKIP 0x0
#define TFT_VBUFFER_YCROP 0
#define SINGLELINE_RENDERING 1
#define CUSTOM_SND 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
#define FILEBROWSER
// Title: < >
#define TITLE " AtariST Emulator "
#define ROMSDIR "st"
#define emu_Init(ROM) {ast_Init(); ast_Start(ROM);}
#define emu_Step(x) {ast_Step();}
#define emu_Input(x) {ast_Input(x);}
#ifdef KEYMAP_PRESENT
#ifdef PICOZX
const unsigned short key_map1[] = {
2,3,4,5,6,7,8,9,10,1,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0
};
const unsigned short key_map2[] = {
0,0,11,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,12,0,0,0,0,
0,0,0,0,0,0
};
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0
};
const unsigned short matkeys[] = {
0x104,0x101,0x108,0x102,0x110,0x120,0x140,0x204,0x201,0x208, // row 1
0x202,0x210,0x220,0x240,0x304,0x301,0x308,0x302,0x310,0x320, // row 2
0x340,0x404,0x401,0x408,0x402,0x410,0x420,0x440,0x504,0x501, // row 3
0x020,0x508,0x502,0x510,0x520,0x540,0x604,0x601,0x040,0x608, // row 4
0x008,0x001,0x002,0x010,0x620,0x640 }; // cursor keys up, left, right, down, <<<, >>>
#else
#define keylables_map1_0 (char *)"1234567890 "
#define keylables_map1_1 (char *)" # * "
#define keylables_map1_2 (char *)" "
const unsigned short key_map1[] = {
2,3,4,5,6,7,8,9,10,1,0,
0,0,0,11,0,0,0,0,12,0,0,
0, 0,0,0,0,0,0,0,0,0,
0,0,0,0
};
/*
const unsigned short key_map1[] = {
2,3,4,
5,6,7,
8,9,10,
11,1,12};
*/
#define keylables_map2_0 (char *)" "
#define keylables_map2_1 (char *)" "
#define keylables_map2_2 (char *)" "
const unsigned short key_map2[] = {
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0,
0,0,0,0
};
#define keylables_map3_0 (char *)" "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" "
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0,
0,0,0,0
};
const unsigned short matkeys[] = {
0x020,0x120,0x220,0x320,0x420,0x408,0x308,0x208,0x108,0x008,0x002, // row 1
0x510,0x010,0x110,0x210,0x310,0x410,0x401,0x301,0x201,0x101,0x001, // row 2
0x520,0x102,0x202,0x302,0x402,0x404,0x304,0x204,0x104,0x004, // row 3
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif
#endif

Wyświetl plik

@ -0,0 +1,190 @@
/******************************************************************************/
/* FAME Fast and Accurate Motorola 68000 Emulation Core */
/* (c) 2002 Oscar Orallo Pelaez / Daniel Lancha Garcia */
/* Version: 2.1 */
/* Date: 11-26-2006 */
/* See FAME.HTML for documentation and license information */
/******************************************************************************/
#ifndef __FAME_H__
#define __FAME_H__
#if defined(__cplusplus) && !defined(USE_FAME_CORE_C)
extern "C" {
#endif
/************************************/
/* General library defines */
/************************************/
#ifndef M68K_OK
#define M68K_OK 0
#endif
#ifndef M68K_RUNNING
#define M68K_RUNNING 1
#endif
#ifndef M68K_NO_SUP_ADDR_SPACE
#define M68K_NO_SUP_ADDR_SPACE 2
#endif
#ifndef M68K_INV_REG
#define M68K_INV_REG -1
#endif
/* Hardware interrupt state */
#ifndef M68K_IRQ_LEVEL_ERROR
#define M68K_IRQ_LEVEL_ERROR -1
#endif
#ifndef M68K_IRQ_INV_PARAMS
#define M68K_IRQ_INV_PARAMS -2
#endif
/* Defines to specify hardware interrupt type */
#ifndef M68K_AUTOVECTORED_IRQ
#define M68K_AUTOVECTORED_IRQ -1
#endif
#ifndef M68K_SPURIOUS_IRQ
#define M68K_SPURIOUS_IRQ -2
#endif
/* Defines to specify address space */
#ifndef M68K_SUP_ADDR_SPACE
#define M68K_SUP_ADDR_SPACE 0
#endif
#ifndef M68K_USER_ADDR_SPACE
#define M68K_USER_ADDR_SPACE 2
#endif
#ifndef M68K_PROG_ADDR_SPACE
#define M68K_PROG_ADDR_SPACE 0
#endif
#ifndef M68K_DATA_ADDR_SPACE
#define M68K_DATA_ADDR_SPACE 1
#endif
/*******************/
/* Data definition */
/*******************/
/* M68K registers */
typedef enum
{
M68K_REG_D0=0,
M68K_REG_D1,
M68K_REG_D2,
M68K_REG_D3,
M68K_REG_D4,
M68K_REG_D5,
M68K_REG_D6,
M68K_REG_D7,
M68K_REG_A0,
M68K_REG_A1,
M68K_REG_A2,
M68K_REG_A3,
M68K_REG_A4,
M68K_REG_A5,
M68K_REG_A6,
M68K_REG_A7,
M68K_REG_ASP,
M68K_REG_PC,
M68K_REG_SR
} m68k_register;
/* The memory blocks must be in native (Motorola) format */
typedef struct
{
unsigned low_addr;
unsigned high_addr;
unsigned offset;
} M68K_PROGRAM;
/* The memory blocks must be in native (Motorola) format */
typedef struct
{
unsigned low_addr;
unsigned high_addr;
void *mem_handler;
void *data;
} M68K_DATA;
/* M68K CPU CONTEXT */
typedef struct
{
M68K_PROGRAM *fetch;
M68K_DATA *read_byte;
M68K_DATA *read_word;
M68K_DATA *write_byte;
M68K_DATA *write_word;
M68K_PROGRAM *sv_fetch;
M68K_DATA *sv_read_byte;
M68K_DATA *sv_read_word;
M68K_DATA *sv_write_byte;
M68K_DATA *sv_write_word;
M68K_PROGRAM *user_fetch;
M68K_DATA *user_read_byte;
M68K_DATA *user_read_word;
M68K_DATA *user_write_byte;
M68K_DATA *user_write_word;
void (*reset_handler)(void);
void (*iack_handler)(unsigned level);
unsigned * icust_handler;
unsigned dreg[8];
unsigned areg[8];
unsigned asp;
unsigned pc;
unsigned cycles_counter;
unsigned char interrupts[8];
unsigned short sr;
unsigned short execinfo;
} M68K_CONTEXT;
/************************/
/* Function definition */
/************************/
/* General purpose functions */
void m68k_init(void);
unsigned m68k_reset(void);
void m68k_emulate(int n);
unsigned m68k_get_pc(void);
unsigned m68k_get_cpu_state(void);
int m68k_fetch(unsigned address, unsigned memory_space);
/* Interrupt handling functions */
int m68k_raise_irq(int level, int vector);
int m68k_lower_irq(int level);
int m68k_get_irq_vector(int level);
int m68k_change_irq_vector(int level, int vector);
/* CPU context handling functions */
int m68k_get_context_size(void);
void m68k_get_context(void *context);
void m68k_set_context(void *context);
int m68k_get_register(m68k_register reg);
int m68k_set_register(m68k_register reg, unsigned value);
/* Timing functions */
unsigned m68k_get_cycles_counter(void);
unsigned m68k_trip_cycles_counter(void);
unsigned m68k_control_cycles_counter(int n);
void m68k_release_timeslice(void);
void m68k_stop_emulating(void);
void m68k_add_cycles(int cycles);
void m68k_release_cycles(int cycles);
#if defined(__cplusplus) && !defined(USE_FAME_CORE_C)
}
#endif
#endif

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,435 @@
/*
* Castaway
* (C) 1994 - 2002 Martin Doering, Joachim Hoenig
*
* fdc.c - wd1772/dma emulation
*
* This file is distributed under the GPL, version 2 or at your
* option any later version. See doc/license.txt for details.
*
* revision history
* 23.05.2002 0.02.00 JH FAST1.0.1 code import: KR -> ANSI, restructuring
* 09.06.2002 0.02.00 JH Renamed io.c to st.c again (io.h conflicts with system headers)
*/
static char sccsid[] = "$Id: fdc.c,v 1.2 2002/06/08 23:31:58 jhoenig Exp $";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dcastaway.h"
#include "st.h"
#include "mem.h"
#include "m68k_intrf.h"
#include "emuapi.h"
#include "diskapi.h"
#define DISK 1
#define DISKNULL \
"\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0"
int fdc_commands_executed=0;
/*
* FDC Registers
*/
extern int readdsk;
unsigned char fdc_data, fdc_track, fdc_sector, fdc_status, fdc_command, fdc_motor;
unsigned char fdc_int = 0;
char fdcdir=1;
unsigned char disk_ejected[2]={0,1};
unsigned char disk_changed[2];
struct Disk disk[2] = {
{ NULL, DISKNULL, 0, SIDES, TRACKS, SECTORS, SECSIZE },
{ NULL, DISKNULL, 0, SIDES, TRACKS, SECTORS, SECSIZE },
};
typedef struct {
uint16 ID; // Word ID marker, should be $0E0F
uint16 SectorsPerTrack; // Word Sectors per track
uint16 Sides; // Word Sides (0 or 1; add 1 to this to get correct number of sides)
uint16 StartingTrack; // Word Starting track (0-based)
uint16 EndingTrack; // Word Ending track (0-based)
} MSAHEADERSTRUCT;
unsigned char *disc[2];
int discpos[2];
int discread(unsigned long address,int a,int len,int discn)
{
address &= MEMADDRMASK;
int i;
uint8 buf[256];
int totlen = len;
while (totlen>=256) {
disk_Read(buf,256);
totlen -= 256;
for (i=0; i<256; i++) {
WriteB(address, buf[i]);
address++;
}
}
if (totlen) {
disk_Read(buf,totlen);
for (i=0; i<totlen; i++) {
WriteB(address, buf[i]);
address++;
}
}
discpos[discn]=discpos[discn]+i;
readdsk |= ( discn + 1 );
return len;
}
int discwrite(unsigned long address,int a,int len,int discn)
{
address &= MEMADDRMASK;
int i;
#ifdef BYTES_SWAP
uint8 val1,val2;
for (i=0; i<len; i+=2) {
val1 = disc[discn][discpos[discn]+i];
val2 = disc[discn][discpos[discn]+i+1];
disc[discn][discpos[discn]+i] = val2;
disc[discn][discpos[discn]+i+1] =val1;
}
#endif
discpos[discn]=discpos[discn]+i;
return len;
}
int discseek(int discn,int pos,int a)
{
if (pos>(1050*1024)){
return -1;
}
discpos[discn]=pos;
if (disk[discn].file) disk_Seek(pos); //fseek(disk[discn].file,pos,SEEK_SET);
return 0;
}
int FDCInit(int i)
{
unsigned char *buf;
memset((void *)&disc[i][0],0,256);
int len,len2,calcsides,calcsectors,calctracks,badbootsector;
discpos[i]=0;
len = disk_Size(disk[i].name);
disk[i].file = disk_Open(disk[i].name);
buf=&disc[i][0];
disk[i].disksize = len;
if (disk[i].file) {
disk_Read(buf, 256);
disk_Seek(0);
}
disk[i].head = 0;
disk[i].sides = (int) *(buf + 26);
disk[i].sectors = (int) *(buf + 24);
disk[i].secsize = 512; //(int) ((*(buf + 12) << 8) | *(buf + 11));
if (disk[i].sectors * disk[i].sides)
disk[i].tracks = (int) ((*(buf + 20) << 8) | *(buf + 19)) /
(disk[i].sectors * disk[i].sides);
// Second Check more precise
if (len> (500*1024)) calcsides = 2;
else calcsides = 1;
if (!(((len/calcsides)/512)%9)&&(((len/calcsides)/512)/9)<86) calcsectors=9;
else if (!(((len/calcsides)/512)%10)&&(((len/calcsides)/512)/10)<86) calcsectors=10;
else if (!(((len/calcsides)/512)%11)&&(((len/calcsides)/512)/11)<86) calcsectors=11;
else if (!(((len/calcsides)/512)%12)) calcsectors=12;
calctracks =((len/calcsides)/512)/calcsectors;
if (disk[i].sides!=calcsides||disk[i].sectors!=calcsectors||disk[i].tracks!=calctracks){
if (disk[i].sides==calcsides&&disk[i].sectors==calcsectors)
{
disk[i].tracks=calctracks;
badbootsector=0;
}
else
{
disk[i].sides=calcsides;
disk[i].tracks=calctracks;
disk[i].sectors=calcsectors;
badbootsector=(i<<24)|(calcsides<<16)|(calctracks<<8)|(calcsectors);
}
} else{
badbootsector=0;
}
disk_ejected[i]=0;
disk_changed[i]=1;
fdc_status |= 0x40;
disk[i].head = 0;
fdc_track = 0;
return badbootsector;
}
void FDCchange(int i) {
disk[(i>>24)&0xff].sides=(i>>16)&0xff;
disk[(i>>24)&0xff].tracks=(i>>8)&0xff;
disk[(i>>24)&0xff].sectors=i&0xff;
}
void FDCeject(int num) {
disk[num].file = NULL;
sprintf(disk[num].name,"disk%01d",num);
disk[num].sides = SIDES;
disk[num].tracks = TRACKS;
disk[num].sectors = SECTORS;
disk[num].secsize = 512;
disk_ejected[num]=1;
fdc_status |= 0x40;
}
void FDCCommand(void)
{
static char motor = 1;
int sides, drives;
long address; /* dma target/source address */
long offset; /* offset in disk file */
unsigned long count; /* number of byte to transfer */
int n;
if (fdc_commands_executed<64)
fdc_commands_executed++;
/* DMA target/source address */
address = (dma_adrh << 16) + (dma_adrm << 8) + dma_adrl;
/* status of side select and drive select lines */
sides = (~psg[14]) & 0x1;
drives = (~psg[14]) & 0x6;
if (disk_ejected[drives>>2]==1) drives=2;
switch (drives) {
case 2: /* Drive A */
drives = 0;
break;
case 4: /* Drive B */
drives = 1;
break;
case 6: /* both, error */
case 0: /* no drive selected */
drives = -1;
break;
}
fdc_status = 0; /* clear fdc status */
#if DISK
if (fdc_command < 0x80) { /* TYPE-I fdc commands */
if (drives >= 0) { /* drive selected */
switch (fdc_command & 0xf0) {
case 0x00: /* RESTORE */
disk[drives].head = 0;
fdc_track = 0;
break;
case 0x10: /* SEEK */
disk[drives].head += (fdc_data - fdc_track);
fdc_track = fdc_data;
if (disk[drives].head < 0
|| disk[drives].head >= disk[drives].tracks)
disk[drives].head = 0;
break;
case 0x30: /* STEP */
fdc_track += fdcdir;
case 0x20:
disk[drives].head += fdcdir;
break;
case 0x50: /* STEP-IN */
fdc_track++;
case 0x40:
if (disk[drives].head < disk[drives].tracks)
disk[drives].head++;
fdcdir = 1;
break;
case 0x70: /* STEP-OUT */
fdc_track--;
case 0x60:
if (disk[drives].head > 0)
disk[drives].head--;
fdcdir = -1;
break;
}
if (disk[drives].head == 0) {
fdc_status |= 0x4;
}
if (disk[drives].head != fdc_track && fdc_command & 0x4) { /* Verify? */
fdc_status |= 0x10;
}
if (motor) {
fdc_status |= 0x20; /* spin-up flag */
}
} else { /* no drive selected */
fdc_status |= 0x10;
}
} else if ((fdc_command & 0xf0) == 0xd0) { /* FORCE INTERRUPT */
if (fdc_command == 0xd8) {
fdc_int = 1;
} else if (fdc_command == 0xd0) {
fdc_int = 0;
}
} else { /* OTHERS */
if (drives >= 0) { /* drive selected */
/* offset within floppy-file */
offset = disk[drives].secsize *
(((disk[drives].sectors * disk[drives].sides * disk[drives].head))
+ (disk[drives].sectors * sides) + (fdc_sector - 1));
switch (fdc_command & 0xf0) {
case 0x80: /* READ SECTOR */
count = 512;
if (!discseek (drives, offset, 0)) {
if (address<MEMSIZE){
if (count == discread (address, 1, count, drives)) {
address += count;
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
break;
}
}else{
address += count;
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
mfp_gpip |= 0x20;
fdc_status |= 0x1;
break;
}
}
fdc_status |= 0x10;
dma_sr = 1;
break;
case 0x90: /* READ SECTOR multiple */
count = dma_scr * 512;
if (count+(fdc_sector-1)*512>disk[drives].sectors*512) count=disk[drives].sectors*512-(fdc_sector-1)*512;
if (!discseek (drives, offset, 0)) {
if (address<MEMSIZE){
if (count == discread (address, 1, count, drives)) {
address += count;
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
fdc_sector += count/disk[drives].secsize;
break;
}
}else{
address += count;
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
mfp_gpip |= 0x20;
fdc_status |= 0x1;
break;
}
}
fdc_status |= 0x10;
dma_sr = 1;
break;
case 0xa0: /* WRITE SECTOR */
count = dma_scr * 512;
if (!discseek (drives, offset, 0)) {
if (count == discwrite (address, 1, count, drives)) {
address += count;
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
break;
}
}
fdc_status |= 0x10;
dma_sr = 1;
break;
case 0xb0: /* WRITE SECTOR multiple */
count = dma_scr * 512;
if (!discseek (drives, offset, 0)) {
if (count == discwrite (address, 1, count, drives)) {
address += count;
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
fdc_sector += dma_scr * (512 / disk[drives].secsize);
break;
}
}
fdc_status |= 0x10;
dma_sr = 1;
break;
case 0xc0: /* READ ADDRESS */
fdc_status |= 0x10;
break;
case 0xe0: /* READ TRACK */
count = disk[drives].sectors * 512;
offset = disk[drives].secsize *
(((disk[drives].sectors * disk[drives].sides * disk[drives].head))
+ (disk[drives].sectors * sides));
if (!discseek (drives, offset, 0)) {
if (address<MEMSIZE){
if (dma_scr==0x1f){
count=0;
address += 302;
}
if (count == discread (address, 1, count, drives)) {
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
break;
}
}else{
address += 302;
dma_adrl = address & 0xff;
dma_adrm = (address >> 8) & 0xff;
dma_adrh = (address >> 16) & 0xff;
dma_scr = 0;
dma_sr = 1;
mfp_gpip |= 0x20;
fdc_status |= 0x1;
break;
}
}
fdc_status |= 0x10;
dma_sr = 1;
break;
case 0xf0: /* WRITE TRACK */
fdc_status |= 0x10;
break;
}
if (disk[drives].head != fdc_track) {
fdc_status |= 0x10;
}
} else {
fdc_status |= 0x10; /* no drive selected */
}
}
#endif
if (motor) {
fdc_status |= 0x80; /* motor on flag */
fdc_motor=1;
}
if (!(fdc_status & 0x01)) { /* not busy */
mfp_iprb |= (0x80 & mfp_ierb); /* Request Interrupt */
mfp_gpip &= ~0x20;
}
}

Wyświetl plik

@ -0,0 +1,523 @@
/*
* Castaway
* (C) 1994 - 2002 Martin Doering, Joachim Hoenig
*
* ikbd.c - ST keyboard processor emulator (german keymap)
*
* This file is distributed under the GPL, version 2 or at your
* option any later version. See doc/license.txt for details.
*
* revision history
* 23.05.2002 0.02.00 JH FAST1.0.1 code import: KR -> ANSI, restructuring
* 09.06.2002 0.02.00 JH Renamed io.c to st.c again (io.h conflicts with system headers)
* 16.06.2002 0.02.00 JH New function: IkbdQueryBuffer(). X11 keysym conversion removed.
*/
static char sccsid[] = "$Id: ikbd.c,v 1.3 2002/06/16 23:16:09 jhoenig Exp $";
//#include "winbase.h"
#include <stdio.h>
#include <string.h>
#include "dcastaway.h"
#include "st.h"
#define IBS 10 /* Ikbd input buffer size */
#define OBS 20 /* Ikbd output buffer size */
//extern char Msg[400];
extern FILE* logfile;
extern int exmousex,exmousey;
int pause = 0;
struct _mouse mouse;
struct _joystick joystick;
extern unsigned char joynum;
unsigned char inbuff[IBS];
unsigned char outbuff[OBS];
int inbuffi = 0;
int outbuffi = 0;
int oldjoystate =0;
int joytick=0;
unsigned char Buttons;
//SYSTEMTIME SystemTime;
unsigned char TempButtons=0x0a;
unsigned char PrevButtons;
unsigned char Misc_ConvertToBCD(unsigned short int Value)
{
return( ((Value&0xf0)>>4)*10 + (Value&0x0f) );
}
void IkbdRecv(unsigned char inchar)
{
if (inbuffi == IBS) {
inbuffi = 0;
}
inbuff[inbuffi++] = inchar;
//Serial.print("d ");
//Serial.println(inbuff[0]);
switch (inbuff[0]) {
case 0x07: /* set mouse button action */
if (inbuffi == 2) {
inbuffi = 0;
mouse.button_action = inbuff[1];
}
break;
case 0x08: /* set relative mouse position reporting */
inbuffi = 0;
mouse.mode = 1;
break;
case 0x09: /* set absolute mouse positioning */
if (inbuffi == 5) {
mouse.mode = 2;
mouse.xmax = (inbuff[1] << 8) | inbuff[2];
mouse.ymax = (inbuff[3] << 8) | inbuff[4];
mouse.x=mouse.xmax/2;
mouse.y=mouse.ymax/2;
inbuffi = 0;
}
break;
case 0x0a: /* set mouse keycode mode */
if (inbuffi == 3) {
mouse.mode = 3;
mouse.xkcm = inbuff[1];
mouse.ykcm = inbuff[2];
inbuffi = 0;
}
break;
case 0x0b: /* set mouse threshold */
if (inbuffi == 3) {
mouse.xth = inbuff[1];
mouse.yth = inbuff[2];
inbuffi = 0;
}
break;
case 0x0c: /* set mouse scale */
if (inbuffi == 3) {
mouse.xscale = inbuff[1];
mouse.yscale = inbuff[2];
inbuffi = 0;
}
break;
case 0x0d: /* interrogate mouse position */
if (outbuffi < (OBS -6)){
inbuffi = 0;
/* Test buttons */
Buttons = 0;
/* Set buttons to show if up/down */
if (mouse.stbuttons&1) Buttons |= 0x01; else Buttons |= 0x02;
if (mouse.stbuttons&2) Buttons |= 0x04; else Buttons |= 0x08;
/* Mask off it didn't send last time */
PrevButtons = TempButtons;
TempButtons = Buttons;
Buttons &= ~PrevButtons;
IkbdSend (0xf7);
IkbdSend (Buttons);
IkbdSend (mouse.stx >> 8);
IkbdSend (mouse.stx);
IkbdSend (mouse.sty >> 8);
IkbdSend (mouse.sty);
}
break;
case 0x0e: /* load mouse position */
if (inbuffi == 6) {
inbuffi = 0;
mouse.x = exmousex = mouse.stx = (inbuff[2] << 8) | inbuff[3];
mouse.y = exmousey = mouse.sty = (inbuff[4] << 8) | inbuff[5];
}
break;
case 0x0f: /* set Y=0 at bottom */
inbuffi = 0;
mouse.yinv = 1;
break;
case 0x10: /* set Y=0 at top */
inbuffi = 0;
mouse.yinv = 0;
break;
case 0x11: /* resume */
inbuffi = 0;
pause = 0;
break;
case 0x12: /* disable mouse */
inbuffi = 0;
//mouse.mode = 0;
break;
case 0x13: /* pause output */
inbuffi = 0;
//pause = 1;
break;
case 0x14: /* set joystick event reporting */
inbuffi = 0;
joystick.mode = 1;
break;
case 0x15: /* set joystick interrogation mode */
inbuffi = 0;
joystick.mode = 2;
break;
case 0x16: /* joystick interrogation */
inbuffi = 0;
IkbdSend (0xfd);
IkbdSend (0);
IkbdSend (oldjoystate);
break;
case 0x17: /* set joystick monitoring */
if (inbuffi == 2) {
inbuffi = 0;
joystick.rate = inbuff[1];
joystick.mode = 4;
}
break;
case 0x18: /* set fire button monitoring */
inbuffi = 0;
joystick.mode = 5;
break;
case 0x19: /* set joystick keycode mode */
if (inbuffi == 7) {
inbuffi = 0;
joystick.mode = 3;
}
break;
case 0x1a: /* disable joysticks */
inbuffi = 0;
// joystick.mode = 0;
break;
case 0x1b: /* time-of-day clock set */
if (inbuffi == 7) {
inbuffi = 0;
}
break;
case 0x1c: /* interrogate time-of-day clock */
inbuffi = 0;
IkbdSend (0xfc);
IkbdSend (0x0);
IkbdSend (0x0);
IkbdSend (0x0);
IkbdSend (0x0);
IkbdSend (0x0);
IkbdSend (0x0);
break;
case 0x20: /* memory load */
case 0x21: /* memory read */
case 0x22: /* controller execute */
inbuffi = 0;
break;
case 0x80: /* reset */
if (inbuffi == 2) {
IkbdSend (0xf0);
inbuffi = 0;
mouse.buttons = mouse.stbuttons = 0;
switch (vid_shiftmode) {
case 0:
mouse.x = exmousex = mouse.stx = 160;
mouse.y = exmousey = mouse.sty = 100;
break;
case 1:
mouse.x = exmousex = mouse.stx = 320;
mouse.y = exmousey = mouse.sty = 100;
break;
case 2:
mouse.x = exmousex = mouse.stx = 320;
mouse.y = exmousey = mouse.sty = 200;
break;
}
}
break;
case 0x87: /* request button action */
IkbdSend (0x07);
IkbdSend (mouse.button_action);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
break;
case 0x88: /* request mouse mode */
case 0x89:
case 0x8a:
switch (mouse.mode) {
case 1:
IkbdSend (0x08);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
break;
case 2:
IkbdSend (0x09);
IkbdSend (mouse.xmax >> 8);
IkbdSend (mouse.xmax);
IkbdSend (mouse.ymax >> 8);
IkbdSend (mouse.ymax);
IkbdSend (0);
IkbdSend (0);
break;
case 3:
IkbdSend (0x09);
IkbdSend (mouse.xkcm);
IkbdSend (mouse.ykcm);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
break;
}
inbuffi = 0;
mouse.mode = 1;
break;
case 0x8b: /* request mouse threshold */
IkbdSend (0x0b);
IkbdSend (mouse.xth);
IkbdSend (mouse.yth);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
inbuffi = 0;
break;
case 0x8c: /* request mouse scale */
IkbdSend (0x0b);
IkbdSend (mouse.xscale);
IkbdSend (mouse.yscale);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
inbuffi = 0;
break;
case 0x8f: /* request mouse vertical coordinates */
case 0x90:
if (mouse.yinv)
IkbdSend (0x0f);
else
IkbdSend (0x10);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
inbuffi = 0;
break;
case 0x92: /* disable mouse */
if (mouse.mode)
IkbdSend (0);
else
IkbdSend (0x12);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
inbuffi = 0;
break;
case 0x94: /* request joystick mode */
case 0x95:
case 0x99: /* set joystick keycode mode */
inbuffi = 0;
switch (joystick.mode) {
case 1:
IkbdSend (0x14);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
break;
case 2:
IkbdSend (0x15);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
IkbdSend (0);
break;
case 3:
IkbdSend (0x19);
IkbdSend (joystick.rx);
IkbdSend (joystick.ry);
IkbdSend (joystick.tx);
IkbdSend (joystick.ty);
IkbdSend (joystick.vx);
IkbdSend (joystick.vy);
break;
}
inbuffi = 0;
break;
case 0x9a: /* request joystick availability */
if (joystick.mode)
IkbdSend (0);
else
IkbdSend (0x1a);
IkbdSend (joystick.rx);
IkbdSend (joystick.ry);
IkbdSend (joystick.tx);
IkbdSend (joystick.ty);
IkbdSend (joystick.vx);
IkbdSend (joystick.vy);
inbuffi = 0;
break;
}
}
void IkbdSend (unsigned char outchar)
{
if (outbuffi < (OBS - 1)) {
//Serial.print("q ");
//Serial.println(outchar);
outbuff[outbuffi++] = outchar;
}
}
void IkbdWriteBuffer(void)
{
/*
if (mouse.flag && (outbuffi < (OBS / 2))) {
IkbdMouse ();
}
if (joystick.mode==4) IkbdJoystick();
*/
if (outbuffi>0)
{
if ((acia1_sr & 0x1) == 0)
{
//Serial.println("KW");
acia1_sr |= 1;
if (acia1_cr & 0x80) { /* receiver interrupt enabled? */
acia1_sr |= 0x80;
mfp_gpip &= (~0x10);
}
acia1_dr = outbuff[0];
memcpy (&outbuff[0], &outbuff[1], (OBS - 1));
outbuffi--;
}
}
}
void IkbdKeyPress (unsigned short keysym) {
IkbdSend (keysym);
}
void IkbdKeyRelease (unsigned short keysym) {
IkbdSend (0x80 | keysym);
}
void IkbdMouseMotion (int x, int y)
{
if (vid_shiftmode==1) {x+=x;}
if (vid_shiftmode==2) {x+=x; y+=y;}
mouse.x=x; mouse.y=y;
}
void IkbdMousePress (int code) {
mouse.buttons |= code;
}
void IkbdMouseRelease (int code) {
mouse.buttons &= ~code;
}
void joystickevent (int joystate)
{
//Has joystick moved?
if (joystate==oldjoystate) return;
oldjoystate=joystate;
//send fire button to mouse as well
if (mouse.mode==1 || mouse.mode==0) {
if (joystate&0x80) {
IkbdSend (0xf9);
IkbdSend (0);
IkbdSend (0);
}
else {
IkbdSend (0xf8);
IkbdSend (0);
IkbdSend (0);
}
}
//In event mode send the joystick event immediately
if (joystick.mode==1) {
IkbdSend (0xff);
IkbdSend (joystate);
}
}
void IkbdLoop()
{
int dx, dy;
if (mouse.mode==1) {
dx=mouse.x-mouse.stx; if (dx>127) dx=127; else if (dx<-127) dx=-127;
dy=mouse.y-mouse.sty; if (dy>127) dy=127; else if (dy<-127) dy=-127;
if (mouse.stbuttons!=mouse.buttons || dx>mouse.xth || dy>mouse.yth || -dx>mouse.xth || -dy>mouse.yth) {
if (outbuffi<OBS/2) {
mouse.stbuttons = mouse.buttons;
mouse.stx = mouse.stx + dx;
mouse.sty = mouse.sty + dy;
if (mouse.stx <= 0) {mouse.stx = 0; dx = -127;}
if (mouse.sty <= 0) {mouse.sty = 0; dy = -127;}
switch (vid_shiftmode) {
case 0:
if (mouse.stx >= 319) {mouse.stx = 319; dx = 127;}
if (mouse.sty >= 199) {mouse.sty = 199; dy = 127;}
break;
case 1:
if (mouse.stx >= 639) {mouse.stx = 639; dx = 127;}
if (mouse.sty >= 199) {mouse.sty = 199; dy = 127;}
break;
case 2:
if (mouse.stx >= 639) {mouse.stx = 639; dx = 127;}
if (mouse.sty >= 399) {mouse.sty = 399; dy = 127;}
break;
}
IkbdSend (0xf8 | (mouse.stbuttons&3));
IkbdSend (dx);
IkbdSend (dy);
}
}
}
else {
if (mouse.x>mouse.xmax) mouse.x=mouse.xmax;
if (mouse.y>mouse.ymax) mouse.y=mouse.ymax;
mouse.stx=mouse.x;
mouse.sty=mouse.y;
mouse.stbuttons=mouse.buttons;
}
if (joystick.mode==4) {
//Called at 200hz when joystick is in mode 4
joytick+=2;
if (joytick<joystick.rate) return;
joytick=0;
IkbdSend (oldjoystate>>7);
IkbdSend (oldjoystate&15);
}
}
void IkbdReset (void)
{
joystick.mode=1;
mouse.mode=1;
IkbdSend(0x80);
IkbdSend(0xff);
IkbdSend(0x80);
acia1_cr=150;
acia1_sr=0;
acia1_dr=240;
acia2_cr=149;
acia2_sr=0;
acia2_dr=0;
inbuffi = 0;
outbuffi = 0;
}
void IkbdJoystickChange(int number, uint8 state)
{
joystickevent(state);
}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,19 @@
#ifndef keyboard_osd_h_
#define keyboard_osd_h_
extern bool virtualkeyboardIsActive(void);
extern void drawVirtualkeyboard(void);
extern void toggleVirtualkeyboard(bool keepOn);
extern void handleVirtualkeyboard(void);
extern bool callibrationActive(void);
extern int handleCallibration(uint16_t bClick);
extern bool menuActive(void);
extern char * menuSelection(void);
extern void toggleMenu(bool on);
extern int handleMenu(uint16_t bClick);
#endif

Wyświetl plik

@ -0,0 +1,240 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dcastaway.h"
#include "mem.h"
#include "st.h"
#include "m68k_intrf.h"
#ifdef DEBUG_FAME
FILE *fame_debug_file=stdout;
unsigned fame_debug_count=0;
#ifdef DEBUG_FAME_START
int fame_debug_output=0;
#else
int fame_debug_output=1;
#endif
#endif
#ifdef DEBUG_FAME
#include "dis.h"
#endif
static void SetMemWW(unsigned long address, unsigned short value)
{
address &= MEMADDRMASK;
WriteW(address, value);
/*
if (address<RAM1SIZE)
WriteW(address + mem1base, value);
else
WriteW(address-RAM1SIZE + mem2base, value);
*/
}
static void SetMemBB (unsigned long address, unsigned char value) {
address &= MEMADDRMASK;
WriteB(address, value);
/*
if (address<RAM1SIZE)
WriteB(address + mem1base, value);
else
WriteB(address-RAM1SIZE + mem2base, value);
*/
}
static unsigned char GetMemBB(unsigned long address)
{
address &= MEMADDRMASK;
return ReadB(address);
/*
if (address<RAM1SIZE)
return ReadB(address + mem1base);
else
return ReadB(address-RAM1SIZE + mem2base);
*/
}
static unsigned short GetMemWW(unsigned long address)
{
address &= MEMADDRMASK;
return ReadW(address);
/*
if (address<RAM1SIZE)
return ReadW(address + mem1base);
else
return ReadW(address-RAM1SIZE + mem2base);
*/
}
#ifndef USE_FAME_CORE
int recalc_int=1; //0;
#endif
int in_fame_core=0;
int number_exg0_fame=0;
static unsigned addr_exg0_fame=0;
static unsigned pc_exg0_fame=0;
static unsigned sr_exg0_fame=0;
static int rw_exg0_fame=0;
static unsigned long exaddress=0x12345678;
void HWReset(void)
{
m68k_reset();
exaddress=0x12345678;
}
static int inexec=0;
void ExceptionGroup0_execute(void)
{
short context = 0;
#ifdef DEBUG_FAME
if (fame_debug_output)
{ fputs("ExceptionGroup0_execute",fame_debug_file); DEBUG_FAME_FFLUSH; }
#endif
M68KCONTEXT.execinfo&=0x7F;
if ((!((exaddress+1!=addr_exg0_fame)&&(exaddress+2!=addr_exg0_fame)&&(exaddress+3!=addr_exg0_fame))) || (!inexec))
{
if (!inexec)
m68k_reset();
return;
}
inexec=0;
context |= 0x8;
if (rw_exg0_fame)
context |= 0x10;
if (GetS())
context |= 0x4;
if (rw_exg0_fame && addr_exg0_fame == pc_exg0_fame)
context |= 0x2;
else
context |= 0x1;
M68KCONTEXT.sr |= (1<<13);
M68KCONTEXT.sr &= ~(1<<15);
M68KCONTEXT.areg[7]-=14;
SetMemW(M68KCONTEXT.areg[7], context);
SetMemL(M68KCONTEXT.areg[7] + 2, addr_exg0_fame);
SetMemW(M68KCONTEXT.areg[7] + 6, GetMemW(pc_exg0_fame));
SetMemW(M68KCONTEXT.areg[7] + 8, sr_exg0_fame);
SetMemL(M68KCONTEXT.areg[7] + 10, pc_exg0_fame);
M68KCONTEXT.pc=GetMemL((long)number_exg0_fame * 4);
exaddress=addr_exg0_fame;
number_exg0_fame=0;
}
void ExceptionGroup0(
int number, /* trap number */
unsigned long address, /* fault address */
int rw) /* read = true, write = false */
{
#ifdef DEBUG_FAME
if (fame_debug_output)
{ fprintf(fame_debug_file,"ExceptionGroup0(%i,0x%X,%i)\n",number,address,rw); DEBUG_FAME_FFLUSH; }
#endif
if ((exaddress+1!=address)&&(exaddress+2!=address)&&(exaddress+3!=address)&&(!inexec)){
inexec=1;
number_exg0_fame=number;
addr_exg0_fame=address;
rw_exg0_fame=rw;
pc_exg0_fame=M68KCONTEXT.pc;
sr_exg0_fame=M68KCONTEXT.sr;
if (!in_fame_core)
ExceptionGroup0_execute();
else
IO_CYCLE=0;
}
}
static M68K_CONTEXT context;
static M68K_PROGRAM program[]= {
{0, RAM1SIZE-1, (unsigned)0},
{RAM1SIZE, MEMSIZE-1, (unsigned)mem2base},
{ROMBASE2, (IOBASE-1), (unsigned)rombase},
{IOBASE, 0x00FFFFFF, (unsigned)rombase},
{(unsigned)-1,(unsigned)-1,(unsigned)NULL}
};
static M68K_DATA read8[] = {
{0, MEMSIZE-1, (void *)GetMemBB, NULL},
{MEMSIZE, (ROMBASE2)-1, (void *)GetMemB, NULL},
{ROMBASE2, IOBASE-1, NULL, (void *)rombase},
{IOBASE, 0x00FFFFFF, (void *)DoIORB, NULL},
{(unsigned)-1,(unsigned)-1,NULL,NULL}
};
static M68K_DATA read16[] = {
{0, MEMSIZE-1, (void *)GetMemWW, NULL},
{MEMSIZE, (ROMBASE2)-1, (void *)GetMemW, NULL},
{ROMBASE2, IOBASE-1, NULL, (void *)rombase},
{IOBASE, 0x00FFFFFF, (void *)DoIORW, NULL},
{(unsigned)-1,(unsigned)-1,NULL,NULL}
};
static M68K_DATA write8[] = {
{0, MEMSIZE-1, (void *)SetMemBB, NULL},
{MEMSIZE, (IOBASE)-1, (void *)SetMemB, NULL},
{IOBASE, 0x00FFFFFF, (void *)DoIOWB, NULL},
{(unsigned)-1,(unsigned)-1,NULL,NULL}
};
static M68K_DATA write16[] = {
{0, MEMSIZE-1, (void *)SetMemWW, NULL},
{MEMSIZE, (IOBASE)-1, (void *)SetMemW, NULL},
{IOBASE, 0x00FFFFFF, (void *)DoIOWW, NULL},
{(unsigned)-1,(unsigned)-1,NULL,NULL}
};
void initialize_memmap(void)
{
int i;
memset(&context,0,sizeof(M68K_CONTEXT));
context.fetch=context.sv_fetch=context.user_fetch=(M68K_PROGRAM*)&program;
context.read_byte=context.sv_read_byte=context.user_read_byte=(M68K_DATA*)&read8;
context.read_word=context.sv_read_word=context.user_read_word=(M68K_DATA*)&read16;
context.write_byte=context.sv_write_byte=context.user_write_byte=(M68K_DATA*)&write8;
context.write_word=context.sv_write_word=context.user_write_word=(M68K_DATA*)&write16;
for(i=0;program[i].low_addr != ((unsigned)-1);i++)
{
if (program[i].low_addr >= ROMBASE2)
program[i].offset= (((unsigned)rombase)+ROMBASE2)-program[i].low_addr;
//else
// program[i].offset= ((unsigned)membase) - (i*MEMSIZE);
}
#ifdef ALL_IN_RAM
program[0].offset= ((unsigned)mem1base) ;
#else
program[0].offset= ((unsigned)0) ;
#endif
program[1].offset= ((unsigned)mem2base - RAM1SIZE) ;
// read8[0].data=read16[0].data=write8[0].data=write16[0].data=(void *)((unsigned)membase);
read8[2].data=read16[2].data=(void *)((unsigned)rombase);
// read8[0].data=read16[0].data=write8[0].data=write16[0].data=(void *)((unsigned)membase);
// read8[1].data=read16[1].data=write8[1].data=write16[1].data=(void *)((unsigned)membase2-MEM1SIZE);
// read8[3].data=read16[3].data=(void *)((unsigned)rombase);
m68k_init();
m68k_set_context(&context);
m68k_reset();
}

Wyświetl plik

@ -0,0 +1,234 @@
#include <stdio.h>
#include <stdlib.h>
#include "dcastaway.h"
extern int waitstate;
#ifndef USE_FAME_CORE
#include "castaway/68000.h"
#include "castaway/op68k.h"
extern unsigned IO_CYCLE;
static __inline__ unsigned long cpu_loop(unsigned slice) {
extern unsigned long (*jmp_table[8192])(operin);
#define initialize_memmap()
//printf("%8x =>%8x\n",pc,myinst);
#define cpuinst \
address = pc&MEMADDRMASK; \
myinst=biginst=ReadSL(address); \
else { HWReset(); return slice-IO_CYCLE; } \
pc+=2; \
IO_CYCLE-=(*jmp_table[(myinst<<16)>>19])(reg);
register unsigned long *p_reg=(unsigned long *)&reg[0];
register unsigned long address;
register uint32 myinst;
IO_CYCLE=slice;
//Execute 10 instructions
cpuinst
cpuinst
cpuinst
cpuinst
cpuinst
cpuinst
cpuinst
cpuinst
cpuinst
cpuinst
return slice-IO_CYCLE;
#undef cpuinst
}
#else
#include "fame.h"
#if defined(DREAMCAST) || defined(USE_FAME_CORE_C)
#define M68KCONTEXT m68kcontext
#define IO_CYCLE io_cycle_counter
#else
#define M68KCONTEXT _m68kcontext
#define IO_CYCLE __io_cycle_counter
#endif
extern unsigned IO_CYCLE;
//extern struct M68K_CONTEXT M68KCONTEXT;
extern M68K_CONTEXT M68KCONTEXT;
extern int recalc_int;
extern void SetMemW(unsigned long address, unsigned short value);
extern void HWReset(void);
#define GetS() ((M68KCONTEXT.sr >> 13) & 1)
#define GetFC2() GetS()
#define GetI() ((M68KCONTEXT.sr >> 8) & 7)
#ifdef DEBUG_FAME
#define Interrupt(NUM,LEV) \
{ \
extern int fame_debug_output; \
extern FILE *fame_debug_file; \
if (fame_debug_output) \
{ fprintf(fame_debug_file,"Interrupt(%i,%i)\n",(NUM),(LEV)); DEBUG_FAME_FFLUSH; } \
m68k_lower_irq((LEV)); \
m68k_raise_irq((LEV),(NUM)); \
}
#else
#define Interrupt(NUM,LEV) \
{ \
M68KCONTEXT.interrupts[0] |= (1 << (LEV)); \
M68KCONTEXT.interrupts[(LEV)]=(NUM); \
M68KCONTEXT.execinfo &= 0x7F; \
}
#endif
#define ClearInterrupt(LEV) M68KCONTEXT.interrupts[0] &= ~(1 << (LEV))
#define MEMADDRMASK 0x00ffffffl
#define MEMADDRMASKS 0x00fffffel
#define MEMIDXSHIFT 11
#define MEMADDRSIZE (MEMADDRMASK + 1)
#define AUTOINT2 26
#define AUTOINT4 28
#define BUSERR 2
#define ADDRESSERR 3
extern char GetMemB(unsigned long address);
extern short GetMemW(unsigned long address);
extern long GetMemL(unsigned long address);
extern void SetMemB(unsigned long address, unsigned char value);
extern void SetMemW(unsigned long address, unsigned short value);
extern void SetMemL(unsigned long address, unsigned long value);
void initialize_memmap(void);
void ExceptionGroup0( int, unsigned long, int);
void ExceptionGroup0_execute(void);
#ifdef DEBUG_FAME
static char dis_msg[96];
static unsigned short dis_buf[10];
void disassemble68k(char *buf, unsigned short *inst_stream);
static __inline__ unsigned long cpu_loop(unsigned slice)
{
unsigned i;
extern int number_exg0_fame;
extern int in_fame_core;
extern unsigned fame_debug_count;
extern int fame_debug_output;
extern FILE *fame_debug_file;
#ifdef DEBUG_FAME_START
if (fame_debug_count>=((unsigned)(DEBUG_FAME_START)))
fame_debug_output=1;
else {
unsigned long cycles_actual=M68KCONTEXT.cycles_counter;
short lastint=M68KCONTEXT.sr&0x700;
in_fame_core=1;
m68k_emulate(slice);
in_fame_core=0;
fprintf(fame_debug_file,"SLICE(%u) %u (%u) ret=%u (%x %x)\n",slice,fame_debug_count,slice,M68KCONTEXT.cycles_counter-cycles_actual,M68KCONTEXT.execinfo&0x80,M68KCONTEXT.interrupts[0]);
fame_debug_count++;
if (number_exg0_fame)
ExceptionGroup0_execute();
if ((M68KCONTEXT.execinfo&0x80)&&(lastint!=(M68KCONTEXT.sr&0x700)))
M68KCONTEXT.execinfo&=0x7f;
return (M68KCONTEXT.cycles_counter-cycles_actual);
}
if (fame_debug_output)
fprintf(fame_debug_file,"SLICE(%u) %u (%u)\n",slice,fame_debug_count,slice);
#endif
in_fame_core=1;
unsigned long cycles_actual=M68KCONTEXT.cycles_counter;
short lastint=M68KCONTEXT.sr&0x700;
while(M68KCONTEXT.cycles_counter-cycles_actual<slice)
{
if (fame_debug_output)
{
dis_msg[0]= 0;
dis_buf[0]= m68k_fetch(m68k_get_pc(),0);
dis_buf[1]= m68k_fetch(m68k_get_pc()+2,0);
dis_buf[2]= m68k_fetch(m68k_get_pc()+4,0);
dis_buf[3]= m68k_fetch(m68k_get_pc()+6,0);
dis_buf[4]= m68k_fetch(m68k_get_pc()+8,0);
dis_buf[5]= m68k_fetch(m68k_get_pc()+10,0);
dis_buf[6]= m68k_fetch(m68k_get_pc()+12,0);
dis_buf[7]= m68k_fetch(m68k_get_pc()+14,0);
disassemble68k(dis_msg,dis_buf);
fprintf(fame_debug_file,"- PC=%.8X (%s) SR=%.2X - INT=%.2X STAT=%.4X E0=%i\n",m68k_get_pc(), dis_msg, M68KCONTEXT.sr,M68KCONTEXT.interrupts[0],M68KCONTEXT.execinfo,number_exg0_fame);
fprintf(fame_debug_file,"\tD0=%.8X D1=%.8X D2=%.8X D3=%.8X\n",M68KCONTEXT.dreg[0],M68KCONTEXT.dreg[1],M68KCONTEXT.dreg[2],M68KCONTEXT.dreg[3]);
fprintf(fame_debug_file,"\tD4=%.8X D5=%.8X D6=%.8X D7=%.8X\n",M68KCONTEXT.dreg[4],M68KCONTEXT.dreg[5],M68KCONTEXT.dreg[6],M68KCONTEXT.dreg[7]);
fprintf(fame_debug_file,"\tA0=%.8X A1=%.8X A2=%.8X A3=%.8X\n",M68KCONTEXT.areg[0],M68KCONTEXT.areg[1],M68KCONTEXT.areg[2],M68KCONTEXT.areg[3]);
fprintf(fame_debug_file,"\tA4=%.8X A5=%.8X A6=%.8X A7=%.8X\n",M68KCONTEXT.areg[4],M68KCONTEXT.areg[5],M68KCONTEXT.areg[6],M68KCONTEXT.areg[7]);DEBUG_FAME_FFLUSH;
}
m68k_emulate(1);
if (fame_debug_output)
{ fputs(".",fame_debug_file); DEBUG_FAME_FFLUSH; }
if (M68KCONTEXT.execinfo&0x80)
break;
}
in_fame_core=0;
fame_debug_count++;
#ifdef DEBUG_FAME_STOP
if (fame_debug_count>((unsigned)(DEBUG_FAME_STOP)))
{
#ifdef DEBUG_FAME_FILE
extern FILE *fame_debug_file;
if (fame_debug_file)
fclose(fame_debug_file);
fame_debug_file=NULL;
#endif
free(malloc(24*1024*1024)); exit(0); }
#endif
if (number_exg0_fame)
{
ExceptionGroup0_execute();
number_exg0_fame=0;
}
if ((M68KCONTEXT.execinfo&0x80)&&(lastint!=(M68KCONTEXT.sr&0x700)))
M68KCONTEXT.execinfo&=0x7f;
return (M68KCONTEXT.cycles_counter-cycles_actual);
}
#else
static __inline__ unsigned long cpu_loop(unsigned slice)
{
extern int in_fame_core;
extern int number_exg0_fame;
unsigned long cycles_actual=M68KCONTEXT.cycles_counter;
short lastint=M68KCONTEXT.sr&0x700;
in_fame_core=1;
m68k_emulate(slice);
in_fame_core=0;
if (number_exg0_fame)
ExceptionGroup0_execute();
if ((M68KCONTEXT.execinfo&0x80)&&(lastint!=(M68KCONTEXT.sr&0x700)))
M68KCONTEXT.execinfo&=0x7f;
return (M68KCONTEXT.cycles_counter-cycles_actual);
}
#endif
#endif

Wyświetl plik

@ -0,0 +1,222 @@
/*
* Castaway
* (C) 1994 - 2002 Martin Doering, Joachim Hoenig
*
* $File$ - memory read/write
*
* This file is distributed under the GPL, version 2 or at your
* option any later version. See doc/license.txt for details.
*
* revision history
* 23.05.2002 JH FAST1.0.1 code import: KR -> ANSI, restructuring
* 30.05.2002 JH Discontinued using mmap and mprotect, now using
* Martin's memory access jump table.
* 12.06.2002 JH Correct bus error/address error exception stack frame
* 14.06.2002 JH LowRamSetX() functions improved.
* 09.07.2002 JH Now loads any 192k ROM file
* 10.07.2002 MAD Now loads any ROM file
* 16.09.2002 JH Bugfix: Word access on unmapped I/O address stacked
* two bus error stack frames. Fault address corrected.
* 08.10.2002 JH Fixed integer types.
* 27.10.2002 AG Trashed everything for more speed! mwuhahaha!
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#ifndef DREAMCAST
#else
#include <string.h>
#endif
#include "dcastaway.h"
#include "st.h"
#include "mem.h"
#include "m68k_intrf.h"
static unsigned rombase_pos=0;
char rom[80]; // = ROM;
#ifdef DREAMCAST
void reinit_sdcard(void);
char rom_sd[24] = ROM_SD;
#endif
static int samvol[16]={0,0,0,1,1,1,2,3,5,7,11,17,25,38,57,85};
extern uint32 psg[26];
#define lastpsg psg[25]
#define sampos psg[24]
char GetMemB(unsigned long address)
{
address &= MEMADDRMASK;
if (address<MEMSIZE)
return ReadB(address/* + mem1base*/);
else
if (address<ROMBASE2)
return -1;
else
if (address<IOBASE)
return *(uint8*)((uint32)(address + rombase)^1);
//ReadB(address + rombase);
else
if (address<IOBASE+IOSIZE)
return DoIORB(address);
return -1;
}
/* Fetch word, address may not be word-aligned */
short GetMemW(unsigned long address)
{
#ifdef CHKADDRESSERR
address &= MEMADDRMASK;
if (address & 0x1){
ExceptionGroup0(ADDRESSERR, address, 1);
return -1;
}
#else
address &= MEMADDRMASKS;
#endif
if (address<MEMSIZE)
return ReadW(address /*+ mem1base*/);
else
if (address<ROMBASE2)
return -1;
else
if (address<IOBASE)
return *(uint16*)(address + rombase);
//return ReadW(address + rombase);
else
if (address<IOBASE+IOSIZE)
return DoIORW(address);
return -1;
}
/* Fetch dword, address may not be dword-aligned */
long GetMemL(unsigned long address)
{
#ifdef CHKADDRESSERR
address &= MEMADDRMASK;
if (address & 0x1){
ExceptionGroup0(ADDRESSERR, address, 1);
return -1;
}
#else
address &= MEMADDRMASKS;
#endif
if (address<MEMSIZE)
return ReadL(address/* + mem1base*/);
else
if (address<ROMBASE2)
return -1;
if (address<IOBASE)
//ReadL(address + rombase);
return ((*(uint16*)(address + rombase))<<16)|(*(uint16*)(address + rombase+2));
if (address<IOBASE+IOSIZE)
return DoIORL(address);
return -1;
}
/* Write byte to address */
void SetMemB (unsigned long address, unsigned char value)
{
address &= MEMADDRMASK;
ON_WRITE(address, value);
if (address<MEMSIZE) {
//RAM
if (address<SVADDR && !GetFC2()){
ExceptionGroup0(BUSERR, address, 0);
return;
}
WriteB(address/* + mem1base*/, value);
return;
}
if (address>=IOBASE && address<IOBASE+IOSIZE) {
//IO
DoIOWB(address, value);
return;
}
//Unmapped
ON_UNMAPPED(address, value);
}
/* Write word, address may not be word-aligned */
void SetMemW(unsigned long address, unsigned short value)
{
#ifdef CHKADDRESSERR
address &= MEMADDRMASK;
if (address & 0x1){
ExceptionGroup0(ADDRESSERR, address, 1);
return;
}
#else
address &= MEMADDRMASKS;
#endif
ON_WRITE(address, value);
if (address<MEMSIZE) {
//RAM
if (address<SVADDR ){
if (!GetFC2()||address<8){
ExceptionGroup0(BUSERR, address, 0);
return;
}
}
WriteW(address/* + mem1base*/, value);
return;
}
if (address>=IOBASE && address<IOBASE+IOSIZE) {
//IO
DoIOWW(address, value);
return;
}
//Unmapped
ON_UNMAPPED(address, value);
}
/* Write dword, address may not be dword-aligned */
void SetMemL(unsigned long address, unsigned long value)
{
#ifdef CHKADDRESSERR
address &= MEMADDRMASK;
if (address & 0x1){
ExceptionGroup0(ADDRESSERR, address, 1);
return;
}
#else
address &= MEMADDRMASKS;
#endif
ON_WRITE(address, value);
if (address<MEMSIZE) {
//RAM
if (address<SVADDR){
if (!GetFC2()||address<8){
ExceptionGroup0(BUSERR, address, 0);
return;
}
}
#ifdef OPTIMIZE_VMEM
if ( (address >= vid_mem) && (address < (vid_mem+32768) ) ) {
printf("vwlmem\n");
WriteL(&videobuf[address-vid_mem], value);
}
else
#endif
WriteL(address/* + mem1base*/, value);
return;
}
if (address>=IOBASE && address<IOBASE+IOSIZE) {
//IO
DoIOWL(address, value);
return;
}
//Unmapped
ON_UNMAPPED(address, value);
}

Wyświetl plik

@ -0,0 +1,86 @@
//#define ALL_IN_RAM 1
//#define PSRAM_FAKE 1
#ifdef ALL_IN_RAM
#define MEMSIZE 0x00040000L /* default memsize 256 Kb split RAM */
#define RAM1BASE 0x00000000L
#define RAM1SIZE 0x00020000L
#define RAM2BASE RAM1SIZE
extern uint8 *mem1base;
#else
#ifdef PSRAM_FAKE
#define MEMSIZE 0x00040000L /* default memsize 256 Kb split RAM */
#define RAM1BASE 0x00000000L
#define RAM1SIZE 0x00020000L
#define RAM2BASE RAM1SIZE
extern uint8 *mem1base;
#else
//#define MEMSIZE 0x00080000L /* default memsize 512 Kb split PSRAM+RAM */
#define MEMSIZE 0x00100000L /* default memsize 1024 Kb split PSRAM+RAM */
#define RAM1BASE 0x00000000L
//#define RAM1SIZE 0x00030000L
#define RAM1SIZE 0x000B0000L
#define RAM2BASE RAM1SIZE
#endif
#endif
extern uint8 *mem2base;
extern uint8 *rombase;
/*
* Read/Write memory macros - little endian
*/
#ifdef ALL_IN_RAM
#define ReadB(address) *(uint8*)((uint32)(address+mem1base)^1)
#define WriteB(address,value) *(uint8*)((uint32)(address+mem1base)^1)=value
#define ReadW(addr) *(uint16*)(addr+mem1base)
#define WriteW(addr,value) *(uint16*)(addr+mem1base)=value
#define ReadL(address) ((*(uint16*)(address+mem1base))<<16)|(*(uint16*)(address+mem1base+2))
#define WriteL(address,value) WriteW(address + 2, value); WriteW(address, value>> 16)
#define ReadSL(addr) (*(uint16*)(addr+mem1base))|((*(uint16*)(addr+mem1base+2))<<16)
#else
extern unsigned char ram_readb(int address);
extern void ram_writeb(int address, unsigned char val);
extern unsigned short ram_readw(int address);
extern void ram_writew(int address, unsigned short val);
#define ReadBB(address) (address<RAM1SIZE?ram_readb(address):*(address-RAM1SIZE+mem2base))
#define WriteBB(address,value) (address<RAM1SIZE?ram_writeb(address,value):(void)(*(address-RAM1SIZE+mem2base)=value))
#define ReadB(address) (address<RAM1SIZE?ram_readb(address^1):*(uint8*)((uint32)(address-RAM1SIZE+mem2base)^1))
#define WriteB(address,value) (address<RAM1SIZE?ram_writeb(address^1,value):(void)(*(uint8*)((uint32)(address-RAM1SIZE+mem2base)^1)=value))
#define ReadW(address) (address<RAM1SIZE?ram_readw(address):*(uint16*)(address-RAM1SIZE+mem2base))
#define WriteW(address,value) (address<RAM1SIZE?ram_writew(address,value):(void)(*(uint16*)(address-RAM1SIZE+mem2base)=value))
#define ReadL(address) (address<RAM1SIZE?(ram_readw(address)<<16)|(ram_readw(address+2)):((*(uint16*)(address-RAM1SIZE+mem2base))<<16)|(*(uint16*)(address-RAM1SIZE+mem2base+2)))
#define WriteL(address,value) WriteW(address + 2, value); WriteW(address, value>> 16)
#define ReadSL(address) (address<RAM1SIZE?(ram_readw(address))|((ram_readw(address+2))<<16):(*(uint16*)(address-RAM1SIZE+mem2base))|((*(uint16*)(address-RAM1SIZE+mem2base+2))<<16))
/*
#define ReadBB(address) (address<RAM1SIZE?*(mem1base+address):*(address-RAM1SIZE+mem2base))
#define WriteBB(address,value) (address<RAM1SIZE?*(mem1base+address)=value:*(address-RAM1SIZE+mem2base)=value)
#define ReadB(address) (address<RAM1SIZE?*(uint8*)((uint32)(mem1base+address)^1):*(uint8*)((uint32)(address-RAM1SIZE+mem2base)^1))
#define WriteB(address,value) (address<RAM1SIZE?*(uint8*)((uint32)(mem1base+address)^1)=value:*(uint8*)((uint32)(address-RAM1SIZE+mem2base)^1)=value)
#define ReadW(address) (address<RAM1SIZE?*(uint16*)(mem1base+address):*(uint16*)(address-RAM1SIZE+mem2base))
#define WriteW(address,value) (address<RAM1SIZE?*(uint16*)(mem1base+address)=value:*(uint16*)(address-RAM1SIZE+mem2base)=value)
#define ReadL(address) (address<RAM1SIZE?((*(uint16*)(mem1base+address))<<16)|(*(uint16*)(mem1base+address+2)):((*(uint16*)(address-RAM1SIZE+mem2base))<<16)|(*(uint16*)(address-RAM1SIZE+mem2base+2)))
#define WriteL(address,value) WriteW(address + 2, value); WriteW(address, value>> 16)
#define ReadSL(address) (address<RAM1SIZE?(*(uint16*)(mem1base+address))|((*(uint16*)(mem1base+address+2))<<16):(*(uint16*)(address-RAM1SIZE+mem2base))|((*(uint16*)(address-RAM1SIZE+mem2base+2))<<16))
*/
#endif
int MemInit(void);
void MemQuit(void);
void MemClean(void);
void MemReInit(void);
extern unsigned short int TosVersion;
extern short TosCountry;
void TOS_FixRom(uint8 *TosAddress);

Wyświetl plik

@ -0,0 +1,201 @@
#include "pico.h"
#include "pico/stdlib.h"
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include "keyboard_osd.h"
//extern "C" {
#include "emu.h"
//}
#include <stdio.h>
#include <stdio.h>
#include "pico_dsp.h"
volatile bool vbl=true;
bool repeating_timer_callback(struct repeating_timer *t) {
if (vbl) {
vbl = false;
} else {
vbl = true;
}
return true;
}
PICO_DSP tft;
static int skip=0;
#include "hardware/clocks.h"
#include "hardware/vreg.h"
#include "hdmi_framebuffer.h"
//psram_spi_inst_t* async_spi_inst;
int main(void) {
// vreg_set_voltage(VREG_VOLTAGE_1_05);
// set_sys_clock_khz(125000, true);
// set_sys_clock_khz(150000, true);
// set_sys_clock_khz(133000, true);
// set_sys_clock_khz(200000, true);
// set_sys_clock_khz(210000, true);
// set_sys_clock_khz(230000, true);
// set_sys_clock_khz(225000, truxe);
// set_sys_clock_khz(250000, true);
#ifdef HAS_USBPIO
set_sys_clock_khz(140000, true);
#else
set_sys_clock_khz(250000, true);
*((uint32_t *)(0x40010000+0x58)) = 2 << 16; //CLK_HSTX_DIV = 2 << 16; // HSTX clock/2
#endif
// Overclock!
// set_sys_clock_khz(280000, true);
// stdio_init_all();
emu_init();
char * filename;
#ifdef FILEBROWSER
while (true) {
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
filename = menuSelection();
if (action == ACTION_RUN) {
break;
}
tft.waitSync();
}
}
#endif
emu_start();
emu_Init(filename);
tft.startRefresh();
struct repeating_timer timer;
add_repeating_timer_ms(25, repeating_timer_callback, NULL, &timer);
while (true) {
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
}
}
static unsigned short palette16[PALETTE_SIZE];
void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index)
{
if (index<PALETTE_SIZE) {
palette16[index] = RGBVAL16(r,g,b);
}
}
void emu_DrawLinePal16(unsigned char * VBuf, int width, int height, int line)
{
if (skip == 0) {
tft.writeLinePal(width,height,line, VBuf, palette16);
}
}
void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line)
{
if (skip == 0) {
tft.writeLine(width,height,line, VBuf);
}
}
int emu_IsVga(void)
{
return (tft.getMode() == MODE_VGA_320x240?1:0);
}
void emu_DrawVsync(void)
{
skip += 1;
skip &= VID_FRAME_SKIP;
#ifdef HAS_USBPIO
#else
#ifdef USE_VGA
tft.waitSync();
#else
volatile bool vb=vbl;
while (vbl==vb) {};
#endif
#endif
}
/*
void emu_DrawLine8(unsigned char * VBuf, int width, int height, int line)
{
if (skip == 0) {
#ifdef USE_VGA
tft.writeLine(width,height,line, VBuf);
#endif
}
}
void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line)
{
if (skip == 0) {
#ifdef USE_VGA
tft.writeLine16(width,height,line, VBuf);
#else
tft.writeLine(width,height,line, VBuf);
#endif
}
}
void emu_DrawScreen(unsigned char * VBuf, int width, int height, int stride)
{
if (skip == 0) {
#ifdef USE_VGA
tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette8);
#else
tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette16);
#endif
}
}
int emu_FrameSkip(void)
{
return skip;
}
void * emu_LineBuffer(int line)
{
return (void*)tft.getLineBuffer(line);
}
*/
#ifdef HAS_SND
#include "AudioPlaySystem.h"
AudioPlaySystem mymixer;
#define AUDIO_BUFFER_LEN (22050/50)
void emu_sndInit() {
tft.begin_audio(AUDIO_BUFFER_LEN*2, mymixer.snd_Mixer);
mymixer.start();
}
void emu_sndPlaySound(int chan, int volume, int freq)
{
if (chan < 6) {
mymixer.sound(chan, freq, volume);
}
}
void emu_sndPlayBuzz(int size, int val) {
mymixer.buzz(size,val);
}
#endif

Wyświetl plik

@ -0,0 +1,9 @@
#ifndef _PROGRAM_CONFIG_H_
#define _PROGRAM_CONFIG_H_
#define FLASH_STORE_START 0x280000
#define KEYBOARD_ACTIVATED 1
#define NO_SOUND 1
#define HAS_PSRAM 1
#endif

Wyświetl plik

@ -0,0 +1,541 @@
#include "dcastaway.h"
#ifndef NO_SOUND
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "st.h"
#include "mem.h"
#include "m68k_intrf.h"
#include "sound.h"
#define LONGLONG long long
#define ENVELOPE_PERIOD(Fine,Coarse) (((unsigned long)Coarse)<<8) + (unsigned long)Fine
#define NOISE_PERIOD(Freq) ((((unsigned long)Freq)&0x1f)<<11)
#define TONE_PERIOD(Fine,Coarse) ((((unsigned long)Coarse)&0x0f)<<8) + (unsigned long)Fine
#define MIXTABLE_SIZE (256*8) /* Large table, so don't overflow */
#define TONEFREQ_SHIFT 28 /* 4.28 fixed point */
#define NOISEFREQ_SHIFT 28 /* 4.28 fixed point */
#define ENVFREQ_SHIFT 16 /* 16.16 fixed */
#define SAMPLES_BUFFER_SIZE 1024
/* Number of generated samples per frame (eg. 44Khz=882) : */
#define SAMPLES_PER_FRAME ((SOUND_FREQ*2)/50) //((SOUND_FREQ+35)/50)
/* Frequency of generated samples: */
#define SAMPLES_FREQ (SOUND_FREQ)
#define YM_FREQ (2000000/SAMPLES_FREQ) /* YM Frequency 2Mhz */
/* Original wave samples */
/* Shape x Length(repeat 3rd/4th entries) */
#include "tab_EnvelopeShapeValues.h"
//static const int EnvelopeShapeValues[16*1024] = { 1,2 };
/* Use table to convert from (A+B+C) to clipped 'unsigned char' for sound buffer */
/* -ve and +ve range */
#include "tab_MixTable.h"
//static const char MixTable[MIXTABLE_SIZE] = { 1,2 };
static const char *pMixTable = &MixTable[MIXTABLE_SIZE/2]; /* Signed index into above */
/* LogTable */
#include "tab_LogTable.h"
//static const int LogTable[256] = { 1,2 };
#include "tab_LogTable16.h"
//static const int LogTable16[16] = { 1,2 };
static const int *pEnvelopeLogTable = &LogTable[128];
/* Current sample for this time period */
static int Envelope[SAMPLES_BUFFER_SIZE];
static int Noise[SAMPLES_BUFFER_SIZE];
char MixBuffer[MIXBUFFER_SIZE];
/* Frequency and time period samples */
static unsigned long ChannelFreq[3], EnvelopeFreq, NoiseFreq; /* Current frequency of each channel A,B,C,Envelope and Noise */
static int ChannelAmpDecayTime[3]; /* Store counter to show if amplitude is changed to generate 'samples' */
/* Output channel data */
static int Channel_A_Buffer[SAMPLES_BUFFER_SIZE],Channel_B_Buffer[SAMPLES_BUFFER_SIZE],Channel_C_Buffer[SAMPLES_BUFFER_SIZE];
static int ActiveSndBufIdx; /* Current working index into above mix buffer */
static int nSamplesToGenerate; /* How many samples are needed for this time-frame */
/* global values */
bool bWriteEnvelopeFreq; /* Did write to register '13' - causes frequency reset */
bool bWriteChannelAAmp, bWriteChannelBAmp, bWriteChannelCAmp; /* Did write to amplitude registers? */
bool bEnvelopeFreqFlag; /* As above, but cleared each frame for YM saving */
/* Buffer to store circular samples */
int nGeneratedSamples; /* Generated samples since audio buffer update */
int SoundCycles;
/*-----------------------------------------------------------------------*/
/* Envelope shape table */
typedef struct
{
int WaveStart[4], WaveDelta[4];
} ENVSHAPE;
/* Square wave look up table */
static const int SquareWave[16] = { 127,127,127,127,127,127,127,127, -128,-128,-128,-128,-128,-128,-128,-128 };
static long RandomNum;
static __inline__ long Misc_NextLongRand(long Seed)
{
unsigned long Lo, Hi;
Lo = 16807 * (long)(Seed & 0xffff);
Hi = 16807 * (long)((unsigned long)Seed >> 16);
Lo += (Hi & 0x7fff) << 16;
if (Lo > 2147483647L) {
Lo &= 2147483647L;
++Lo;
}
Lo += Hi >> 15;
if (Lo > 2147483647L) {
Lo &= 2147483647L;
++Lo;
}
return((long)Lo);
}
static __inline__ long Misc_GetRandom(void)
{
RandomNum = Misc_NextLongRand(RandomNum);
if (!RandomNum)
{
RandomNum++;
return 0;
}
return(RandomNum);
}
/*-----------------------------------------------------------------------*/
/*
Init sound tables and envelopes
*/
void Sound_Init(void)
{
Sound_Reset();
}
/*-----------------------------------------------------------------------*/
/*
Reset the sound emulation
*/
void Sound_Reset(void)
{
int i;
Sound_ClearMixBuffer(); /* Clear buffer */
/* Clear cycle counts, buffer index and register '13' flags */
SoundCycles = 0;
bEnvelopeFreqFlag = FALSE;
bWriteEnvelopeFreq = FALSE;
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
/* Lock audio system before accessing variables that are also use by the callback function! */
Audio_Lock();
CompleteSndBufIdx = 0;
ActiveSndBufIdx = (SOUND_BUFFER_SIZE + SAMPLES_PER_FRAME) % MIXBUFFER_SIZE;
nGeneratedSamples = 0;
Audio_Unlock();
/* Clear frequency counter */
for(i=0; i<3; i++)
{
ChannelFreq[i] =
ChannelAmpDecayTime[i] = 0;
}
EnvelopeFreq = NoiseFreq = 0;
}
/*-----------------------------------------------------------------------*/
/*
Clear mixer buffer, where samples are stored ready to pass to sound player
*/
void Sound_ClearMixBuffer(void)
{
Audio_Lock();
Memory_Clear(MixBuffer, MIXBUFFER_SIZE); /* Clear buffer */
Audio_Unlock();
}
/*-----------------------------------------------------------------------*/
/*
Find how many samples to generate and store in 'nSamplesToGenerate'
Also update 'SoundCycles' to store how many we actually did so generates set amount each frame
*/
static void Sound_SetSamplesPassed(void)
{
int nSampleCycles;
int nSamplesPerFrame;
int Dec=1;
/* Check how many cycles have passed, as we use this to help find out if we are playing sample data */
/* First, add decay to channel amplitude variables */
if (SoundCycles>(CYCLES_PER_FRAME/4))
Dec = 16; /* Been long time between sound writes, must be normal tone sound */
if (!bWriteChannelAAmp) /* Not written to amplitude, decay value */
{
ChannelAmpDecayTime[0]-=Dec;
if (ChannelAmpDecayTime[0]<0) ChannelAmpDecayTime[0] = 0;
}
if (!bWriteChannelBAmp)
{
ChannelAmpDecayTime[1]-=Dec;
if (ChannelAmpDecayTime[1]<0) ChannelAmpDecayTime[1] = 0;
}
if (!bWriteChannelCAmp)
{
ChannelAmpDecayTime[2]-=Dec;
if (ChannelAmpDecayTime[2]<0) ChannelAmpDecayTime[2] = 0;
}
/* 160256 cycles per VBL, 44Khz = 882 samples per VBL */
/* 882/160256 samples per clock cycle */
nSamplesPerFrame = SAMPLES_PER_FRAME;
#if 0 /* Use floats for calculation */
nSamplesToGenerate = (int)( (float)SoundCycles * ((float)nSamplesPerFrame/(float)CYCLES_PER_FRAME) );
if (nSamplesToGenerate > nSamplesPerFrame)
nSamplesToGenerate = nSamplesPerFrame;
nSampleCycles = (int)( (float)nSamplesToGenerate / ((float)nSamplesPerFrame/(float)CYCLES_PER_FRAME) );
SoundCycles -= nSampleCycles;
#else /* Use integers for calculation - both of these calculations should fit into 32-bit int */
nSamplesToGenerate = SoundCycles * nSamplesPerFrame / CYCLES_PER_FRAME;
//printf("nSamplesToGenerate=%i , SoundCycles=%i\n",nSamplesToGenerate,SoundCycles);
if (nSamplesToGenerate > nSamplesPerFrame)
nSamplesToGenerate = nSamplesPerFrame;
nSampleCycles = nSamplesToGenerate * CYCLES_PER_FRAME / nSamplesPerFrame;
SoundCycles -= nSampleCycles;
#endif
}
/*-----------------------------------------------------------------------*/
/*
Generate envelope wave for this time-frame
*/
static void Sound_GenerateEnvelope(unsigned char EnvShape, unsigned char Fine, unsigned char Coarse)
{
const int *pEnvelopeValues;
unsigned long EnvelopePeriod,EnvelopeFreqDelta;
int i;
/* Find envelope details */
if (bWriteEnvelopeFreq)
EnvelopeFreq = 0;
pEnvelopeValues = &EnvelopeShapeValues[ (EnvShape&0x0f)*1024 ]; /* Envelope shape values */
EnvelopePeriod = ENVELOPE_PERIOD((unsigned long)Fine,(unsigned long)Coarse);
if (EnvelopePeriod==0) /* Handle div by zero */
EnvelopeFreqDelta = 0;
else
EnvelopeFreqDelta = ((LONGLONG)YM_FREQ<<ENVFREQ_SHIFT) / (EnvelopePeriod); /* 16.16 fixed point */
/* Create envelope from current shape and frequency */
for(i=0; i<nSamplesToGenerate; i++)
{
Envelope[i] = pEnvelopeValues[EnvelopeFreq>>ENVFREQ_SHIFT]; /* Store envelope wave, already applied 'log' function */
EnvelopeFreq += EnvelopeFreqDelta;
if (EnvelopeFreq&0xfe000000)
EnvelopeFreq = 0x02000000 | (EnvelopeFreq&0x01ffffff); /* Keep in range 512-1024 once past 511! */
}
}
/*-----------------------------------------------------------------------*/
/*
Generate nosie for this time-frame
*/
static void Sound_GenerateNoise(unsigned char MixerControl, unsigned char NoiseGen)
{
int NoiseValue;
unsigned long NoisePeriod,NoiseFreqDelta;
int i;
NoisePeriod = NOISE_PERIOD((unsigned long)NoiseGen);
if (NoisePeriod==0) /* Handle div by zero */
NoiseFreqDelta = 0;
else
NoiseFreqDelta = (((LONGLONG)YM_FREQ)<<NOISEFREQ_SHIFT) / NoisePeriod; /* 4.28 fixed point */
/* Generate noise samples */
for(i=0; i<nSamplesToGenerate; i++)
{
NoiseValue = (unsigned int)Misc_GetRandom()%96; /* Get random value */
if (SquareWave[NoiseFreq>>NOISEFREQ_SHIFT]<=0) /* Add to square wave at given frequency */
NoiseValue = -NoiseValue;
Noise[i] = NoiseValue;
NoiseFreq += NoiseFreqDelta;
}
}
/*-----------------------------------------------------------------------*/
/*
Generate channel of samples for this time-frame
*/
static void Sound_GenerateChannel(int *pBuffer, unsigned char ToneFine, unsigned char ToneCoarse,unsigned char Amplitude,unsigned char MixerControl,unsigned long *pChannelFreq,int MixMask)
{
int *pNoise = Noise, *pEnvelope = Envelope;
unsigned long ToneFreq=*pChannelFreq;
unsigned long TonePeriod;
unsigned long ToneFreqDelta;
int i,Amp,Mix;
int ToneOutput,NoiseOutput,MixerOutput,EnvelopeOutput,AmplitudeOutput;
TonePeriod = TONE_PERIOD((unsigned long)ToneFine,(unsigned long)ToneCoarse);
/* Find frequency of channel */
if (TonePeriod==0)
ToneFreqDelta = 0; /* Handle div by zero */
else
ToneFreqDelta = (((LONGLONG)YM_FREQ)<<TONEFREQ_SHIFT) / TonePeriod; /* 4.28 fixed point */
Amp = LogTable16[(Amplitude&0x0f)];
Mix = (MixerControl>>MixMask)&9; /* Read I/O Mixer */
/* Check if we are trying to play a 'sample' - we need to up the volume on these as they tend to be rather quiet */
if ((Amplitude&0x10)==0) /* Fixed level amplitude? */
{
ChannelAmpDecayTime[MixMask]++; /* Increment counter to find out if we are playing samples... */
if (ChannelAmpDecayTime[MixMask]>16)
ChannelAmpDecayTime[MixMask] = 16; /* And limit */
}
for(i=0; i<nSamplesToGenerate; i++)
{
/* Output from Tone Generator(0-255) */
ToneOutput = SquareWave[ToneFreq>>TONEFREQ_SHIFT];
/* Output from Noise Generator(0-255) */
NoiseOutput = *pNoise++;
/* Output from Mixer(combines Tone+Noise) */
switch (Mix) {
case 0: /* Has Noise and Tone */
MixerOutput = NoiseOutput+ToneOutput;
break;
case 1: /* Has Noise */
MixerOutput = NoiseOutput;
break;
case 8: /* Has Tone */
MixerOutput = ToneOutput;
break;
default: /* This is used to emulate samples - should give no output, but ST gives set tone!!?? */
/* MixerControl gets set to give a continuous tone and then then Amplitude */
/* of channels A,B and C get changed with all other registers in the PSG */
/* staying as zero's. This produces the sounds from Quartet, Speech, NoiseTracker etc...! */
MixerOutput = 127;
}
EnvelopeOutput = pEnvelopeLogTable[*pEnvelope++];
if ((Amplitude&0x10)==0)
{
AmplitudeOutput = Amp; /* Fixed level amplitude */
/* As with most emulators, sample playback is always 'quiet'. We check to see if */
/* the amplitude of a channel is repeatedly changing and when this is detected we */
/* scale the volume accordingly */
if (ChannelAmpDecayTime[MixMask]>8)
AmplitudeOutput <<= 1; /* Scale up by a factor of 2 */
}
else
AmplitudeOutput = EnvelopeOutput;
*pBuffer++ = (MixerOutput*AmplitudeOutput)>>8;
ToneFreq+=ToneFreqDelta;
}
/* Store back incremented frequency, for next call */
*pChannelFreq = ToneFreq;
}
#ifdef XXX
/*-----------------------------------------------------------------------*/
/*
Generate samples for all channels during this time-frame
*/
static void Sound_GenerateSamples(void)
{
int *pChannelA=Channel_A_Buffer, *pChannelB=Channel_B_Buffer, *pChannelC=Channel_C_Buffer;
int i;
/* Anything to do? */
if (nSamplesToGenerate>0)
{
/* Generate envelope/noise samples for this time */
Sound_GenerateEnvelope(psg[PSG_REG_ENV_SHAPE],psg[PSG_REG_ENV_FINE],psg[PSG_REG_ENV_COARSE]);
Sound_GenerateNoise(psg[PSG_REG_MIXER_CONTROL],psg[PSG_REG_NOISE_GENERATOR]);
/* Generate 3 channels, store to separate buffer so can mix/clip */
Sound_GenerateChannel(pChannelA,psg[PSG_REG_CHANNEL_A_FINE],psg[PSG_REG_CHANNEL_A_COARSE],psg[PSG_REG_CHANNEL_A_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[0],0);
Sound_GenerateChannel(pChannelB,psg[PSG_REG_CHANNEL_B_FINE],psg[PSG_REG_CHANNEL_B_COARSE],psg[PSG_REG_CHANNEL_B_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[1],1);
Sound_GenerateChannel(pChannelC,psg[PSG_REG_CHANNEL_C_FINE],psg[PSG_REG_CHANNEL_C_COARSE],psg[PSG_REG_CHANNEL_C_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[2],2);
/* Mix channels together, using table to clip and also convert to 'unsigned char' */
for(i=0; i<nSamplesToGenerate; i++)
MixBuffer[(i+ActiveSndBufIdx)%MIXBUFFER_SIZE] = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
ActiveSndBufIdx = (ActiveSndBufIdx + nSamplesToGenerate) % MIXBUFFER_SIZE;
nGeneratedSamples += nSamplesToGenerate;
/* Reset the write to register '13' flag */
bWriteEnvelopeFreq = FALSE;
/* And amplitude write flags */
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
}
}
/*-----------------------------------------------------------------------*/
/*
This is called to built samples up until this clock cycle
*/
void Sound_Update(void)
{
int OldSndBufIdx = ActiveSndBufIdx;
/* Find how many to generate */
Sound_SetSamplesPassed();
/* And generate */
Sound_GenerateSamples();
}
/*-----------------------------------------------------------------------*/
/*
This is called from the audio callback function to create enough samples
to fill the current sound buffer.
*/
void Sound_UpdateFromAudioCallBack(void)
{
/* If there are already enough samples or if we are recording, we should
* not generate more samples here! */
if(nGeneratedSamples >= SOUND_BUFFER_SIZE)
return;
nSamplesToGenerate = SOUND_BUFFER_SIZE - nGeneratedSamples;
Sound_GenerateSamples();
Serial.println("vvv");
}
#endif
void Sound_Update(void)
{
int Dec=1;
/* Check how many cycles have passed, as we use this to help find out if we are playing sample data */
/* First, add decay to channel amplitude variables */
if (SoundCycles>(CYCLES_PER_FRAME/4))
Dec = 16; /* Been long time between sound writes, must be normal tone sound */
if (!bWriteChannelAAmp) /* Not written to amplitude, decay value */
{
ChannelAmpDecayTime[0]-=Dec;
if (ChannelAmpDecayTime[0]<0) ChannelAmpDecayTime[0] = 0;
}
if (!bWriteChannelBAmp)
{
ChannelAmpDecayTime[1]-=Dec;
if (ChannelAmpDecayTime[1]<0) ChannelAmpDecayTime[1] = 0;
}
if (!bWriteChannelCAmp)
{
ChannelAmpDecayTime[2]-=Dec;
if (ChannelAmpDecayTime[2]<0) ChannelAmpDecayTime[2] = 0;
}
//Sound_Update();
/* Clear write to register '13', used for YM file saving */
//bEnvelopeFreqFlag = FALSE;
/* Reset the write to register '13' flag */
bWriteEnvelopeFreq = FALSE;
/* And amplitude write flags */
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
}
/*-----------------------------------------------------------------------*/
/*
On each VBL (50fps) complete samples.
*/
void Sound_Update_VBL(void)
{
}
void Sound_UpdateFromCallBack16(short *pBuffer, int len)
{
len = len >> 1;
int *pChannelA=Channel_A_Buffer, *pChannelB=Channel_B_Buffer, *pChannelC=Channel_C_Buffer;
int i;
nSamplesToGenerate = len;
/* Generate envelope/noise samples for this time */
Sound_GenerateEnvelope(psg[PSG_REG_ENV_SHAPE],psg[PSG_REG_ENV_FINE],psg[PSG_REG_ENV_COARSE]);
Sound_GenerateNoise(psg[PSG_REG_MIXER_CONTROL],psg[PSG_REG_NOISE_GENERATOR]);
/* Generate 3 channels, store to separate buffer so can mix/clip */
Sound_GenerateChannel(pChannelA,psg[PSG_REG_CHANNEL_A_FINE],psg[PSG_REG_CHANNEL_A_COARSE],psg[PSG_REG_CHANNEL_A_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[0],0);
Sound_GenerateChannel(pChannelB,psg[PSG_REG_CHANNEL_B_FINE],psg[PSG_REG_CHANNEL_B_COARSE],psg[PSG_REG_CHANNEL_B_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[1],1);
Sound_GenerateChannel(pChannelC,psg[PSG_REG_CHANNEL_C_FINE],psg[PSG_REG_CHANNEL_C_COARSE],psg[PSG_REG_CHANNEL_C_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[2],2);
/* Mix channels together, using table to clip and also convert to 'unsigned char' */
for(i=0; i<len; i++) {
//short s = ((*pChannelA++) +(*pChannelB++) + (*pChannelC++))<<4;
//*pBuffer++ = s;
//*pBuffer++ = s;
//char s = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
short s = (*pChannelA++) + (*pChannelB++) + (*pChannelC++);
*pBuffer++ = (short)s << 7;
s = (*pChannelA++) + (*pChannelB++) + (*pChannelC++);
// s = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
*pBuffer++ = (short)s << 7;
//*pBuffer++ = (short)s << 8;
//*pBuffer++ = 0;
//
}
bWriteEnvelopeFreq = FALSE;
/* And amplitude write flags */
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
}
#else
#warning NO_SOUND
#warning NO_SOUND
#warning NO_SOUND
#warning NO_SOUND
#warning NO_SOUND
#warning NO_SOUND
#endif

Wyświetl plik

@ -0,0 +1,137 @@
#ifndef DCASTAWAY_SOUND_H
#define DCASTAWAY_SOUND_H
#include "dcastaway.h"
#ifndef NO_SOUND
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define MUSIC_VOLUME 64
#ifdef DINGOO
#define SOUND_FREQ 16000
#else
#define SOUND_FREQ 22050 //22050 //11025 //22050
#endif
#define SOUND_BUFFER_SIZE 1024
void Sound_Reset(void);
void Sound_ClearMixBuffer(void);
void Audio_EnableAudio(bool bEnable);
enum
{
FREQ_11Khz,
FREQ_22Khz,
FREQ_44Khz
};
#define MIXBUFFER_SIZE 1024 //8192
#define SCREEN_START_CYCLE 96 /* Cycle first normal pixel appears on */
#define SCANLINES_PER_FRAME 313 /* Number of scan lines per frame */
#define CYCLES_PER_LINE 512 /* Cycles per horiztonal line scan */
#define CYCLES_VBL_IN (SCREEN_START_HBL*CYCLES_PER_LINE) /* ((28+64)*CYCLES_PER_LINE) */
#define CYCLES_PER_FRAME (SCANLINES_PER_FRAME*CYCLES_PER_LINE) /* Cycles per VBL @ 50fps = 160256 */
#define CYCLES_PER_SEC (CYCLES_PER_FRAME*50) /* Cycles per second */
#define CYCLES_ENDLINE (64+320+88+40) /* DE(Display Enable) */
#define CYCLES_HBL (CYCLES_PER_LINE+96) /* Cycles for first HBL - very inaccurate on ST */
#define CYCLES_DEBUGGER 3000 /* Check debugger every 'x' cycles */
enum {
PSG_REG_CHANNEL_A_FINE, // 0x0000
PSG_REG_CHANNEL_A_COARSE, // 0x0001
PSG_REG_CHANNEL_B_FINE, // 0x0010
PSG_REG_CHANNEL_B_COARSE, // 0x0011
PSG_REG_CHANNEL_C_FINE, // 0x0100
PSG_REG_CHANNEL_C_COARSE, // 0x0101
PSG_REG_NOISE_GENERATOR, // 0x0110
PSG_REG_MIXER_CONTROL, // 0x0111
PSG_REG_CHANNEL_A_AMP, // 0x1000
PSG_REG_CHANNEL_B_AMP, // 0x1001
PSG_REG_CHANNEL_C_AMP, // 0x1010
PSG_REG_ENV_FINE, // 0x1011
PSG_REG_ENV_COARSE, // 0x1100
PSG_REG_ENV_SHAPE, // 0x1101
PSG_REG_IO_PORTA, // 0x1110
PSG_REG_IO_PORTB // 0x1111
};
#define NUM_PSG_SOUND_REGISTERS 14 // Number of register, not including IO ports
extern bool bSoundWorking; /* Is sound OK */
extern volatile bool bPlayingBuffer; /* Is playing buffer? */
extern int OutputAudioFreqIndex; /* Playback rate (11Khz,22Khz or 44Khz) */
extern int SoundBufferSize; /* Size of sound buffer */
extern int CompleteSndBufIdx; /* Replay-index into MixBuffer */
extern int SoundPlayBackFrequencies[];
extern bool bWriteEnvelopeFreq,bWriteChannelAAmp,bWriteChannelBAmp,bWriteChannelCAmp;
extern bool bEnvelopeFreqFlag;
extern char MixBuffer[MIXBUFFER_SIZE];
extern int SoundCycles;
extern int nGeneratedSamples;
static __inline__ int Misc_LimitInt(int Value, int MinRange, int MaxRange)
{
if (Value<MinRange)
Value = MinRange;
else if (Value>MaxRange)
Value = MaxRange;
return(Value);
}
#define Memory_Clear(A,B) (memset(A,0,B))
#define Audio_Lock()
#define Audio_Unlock()
void Sound_UpdateFromCallBack16(short *pBuffer, int len);
void Sound_Update_VBL(void);
void Sound_UpdateFromAudioCallBack(void);
void Sound_Init(void);
void Sound_Update(void);
void audio_init(void);
void audio_stop(void);
void audio_init_music(void);
void audio_play_wait(void);
void audio_play_click(void);
void audio_play_file(void);
void audio_play_main(void);
void audio_play_error(void);
void audio_play_goodbye(void);
void audio_play_save(void);
#else
/* NO SOUND */
#define Sound_Update_VBL()
#define Sound_Update()
#define audio_init_music()
#define audio_play_wait()
#define audio_play_click()
#define audio_play_file()
#define audio_play_main()
#define audio_play_error()
#define audio_play_goodbye()
#define audio_play_save()
#define audio_init()
#define audio_stop()
#endif
#endif

Wyświetl plik

@ -0,0 +1,617 @@
/*
* Castaway
* (C) 1994 - 2002 Martin Doering, Joachim Hoenig
*
* IO.c - ST hardware emulation
*
* This file is distributed under the GPL, version 2 or at your
* option any later version. See doc/license.txt for details.
*
* revision history
* 23.05.2002 JH FAST1.0.1 code import: KR -> ANSI, restructuring
* 09.06.2002 JH Renamed io.c to st.c again (io.h conflicts with system headers)
* 12.06.2002 JH Correct bus error/address error exception stack frame
* 14.06.2002 JH Implemented STOP, shutdown CPU after multiple bus errors.
* Removed inst parameter from CPU opcode functions.
* 20.08.2002 JH Fixed sign bug in DoIORW() and DoIORL()
* 10.09.2002 JH Bugfix: MOVE.L 0xfffa00,d0 and the like should not raise bus error
* 16.09.2002 JH Bugfix: Word access on unmapped I/O address stacked
* two bus error stack frames. Fault address corrected.
* Merged some code from JH_TOS206_patches branch.
* 02.10.2002 JH Eliminated a lot of silly bugs introduced recently. Shame on me.
No more CPU bus errors from blitter.c::bitblt().
* 10.10.2002 JH Compatibility improvements.
*/
static char sccsid[] = "$Id: st.c,v 1.14 2002/10/10 19:41:27 jhoenig Exp $";
#include <stdio.h>
#include "dcastaway.h"
#include "st.h"
#include "mem.h"
#include "m68k_intrf.h"
#ifndef NO_SOUND
#include "sound.h"
#endif
#ifdef DEBUG
#include <assert.h>
#endif
#define VALUE_OPEN 0xff
/*
* startup display mode
*/
int display_mode = COL4;
/*
* I/O Registers
*/
uint8 memconf;
//Video shifter
uint32 vid_adr;
uint8 vid_baseh, vid_basem;
uint32 vid_mem=0x10000;
uint8 vid_syncmode=2, vid_shiftmode;
int16 vid_col[16];
int vid_flag;
uint16 dma_car, dma_scr, dma_sr, dma_mode;
uint8 dma_adrh, dma_adrm, dma_adrl;
uint8 mfp_gpip, mfp_aer, mfp_ddr, mfp_iera, mfp_ierb, mfp_ipra,
mfp_iprb, mfp_isra, mfp_isrb, mfp_imra, mfp_imrb, mfp_ivr,
mfp_tacr, mfp_tbcr, mfp_tcdcr, mfp_scr, mfp_ucr, mfp_rsr, mfp_tsr, mfp_udr;
//Mfp delay timer variables
int32 mfp_reg[12];
#define mfp_tadr mfp_reg[0]
#define mfp_tbdr mfp_reg[1]
#define mfp_tcdr mfp_reg[2]
#define mfp_tddr mfp_reg[3]
#define mfp_acount mfp_reg[4]
#define mfp_bcount mfp_reg[5]
#define mfp_ccount mfp_reg[6]
#define mfp_dcount mfp_reg[7]
#define mfp_ascale mfp_reg[8]
#define mfp_bscale mfp_reg[9]
#define mfp_cscale mfp_reg[10]
#define mfp_dscale mfp_reg[11]
uint8 acia1_cr, acia1_sr, acia1_dr, acia2_cr, acia2_sr, acia2_dr;
uint16 blt_halftone[16];
int16 blt_src_x_inc, blt_src_y_inc;
uint32 blt_src_addr;
int16 blt_end_1, blt_end_2, blt_end_3;
int16 blt_dst_x_inc, blt_dst_y_inc;
uint32 blt_dst_addr;
uint16 blt_x_cnt, blt_y_cnt;
int8 blt_hop, blt_op, blt_status, blt_skew;
int8 blt_ready;
uint32 psg[26];
//unsigned char sample[10000];
#define phase0 psg[16]
#define phase1 psg[17]
#define phase2 psg[18]
#define phase3 psg[19]
#define psg_epos psg[20]
#define psgcontrol psg[21]
#define phase4 psg[22]
#define nrand psg[23]
#define sampos psg[24]
#define lastpsg psg[25]
static const int samvol[16]={0,0,0,1,1,1,2,3,5,7,11,17,25,38,57,85};
static int samvol2[4096];
const int32 mfpcycletab[16] = {0,80402,32161,20100,6432,5025,3216,1608,1,0,0,0,0,0,0,0};
void IOInit(void)
{
int n,a,b,c;
//Create sample lookup table (4096 entries)
for (a=0; a<16; a++) {
for (b=0; b<16; b++) {
for (c=0; c<16; c++) {
samvol2[(a<<8)+(b<<4)+c]=samvol[a]+samvol[b]+samvol[c];
}
}
}
//Reset mfp variables
mfp_tadr=256<<20; mfp_tbdr=256<<20; mfp_tcdr=256<<20; mfp_tddr=256<<20;
mfp_tacr=0; mfp_tbcr=0; mfp_tcdcr=0;
mfp_acount=256<<20; mfp_bcount=256<<20; mfp_ccount=256<<20; mfp_dcount=256<<20;
mfp_ascale=0; mfp_bscale=0; mfp_cscale=0; mfp_dscale=0;
for (n=0; n<24; n++) psg[n]=0;
nrand=1;
//Other stuff
vid_baseh = 0;
vid_basem = 0;
vid_shiftmode = display_mode;
dma_sr = 1; /* DMA status ready */
if (display_mode == MONO) {
mfp_gpip = 0x39; /* no lpr, no blt, no interrupt, monochrome */
} else {
mfp_gpip = 0xb9; /* no lpr, no blt, no interrupt, color */
}
#ifdef sun
act.sa_handler = Sigbus;
(void) sigaction (SIGBUS, &act, &oldsigbus);
#endif
#ifdef USE_MMAP
act.sa_handler = Sigsegv;
(void) sigaction (SIGSEGV, &act, &oldsigsegv);
#endif
}
static void update_psg(uint8 value) {
#ifndef NO_SOUND
Sound_Update();
#endif
//Update psg register
psg[psgcontrol]=value;
switch(psgcontrol)
{
case 13:
#ifndef NO_SOUND
bEnvelopeFreqFlag = 1;
bWriteEnvelopeFreq = 1;
#endif
break;
case 12:
psg_epos=0;
break;
case 8:
#ifndef NO_SOUND
bWriteChannelAAmp= 1;
#endif
break;
case 9:
#ifndef NO_SOUND
bWriteChannelBAmp= 1;
#endif
break;
case 10:
#ifndef NO_SOUND
bWriteChannelCAmp= 1;
#endif
break;
}
}
void DoIOWB(uint32 address, uint8 value)
{
address&=0x7fff;
//Video and dma emu
if (address<0x800) {
switch (address) {
case MEM_CONF&0x7fff:
memconf = value;
break;
case VID_BASEH&0x7fff:
vid_baseh = value;
vid_mem = (vid_baseh<<16)+(vid_basem<<8);
break;
case VID_BASEM&0x7fff:
vid_basem = value;
vid_mem = (vid_baseh<<16)+(vid_basem<<8);
break;
case VID_SYNCMODE&0x7fff:
vid_syncmode = value;
maybe_border++;
break;
case VID_SHIFTMODE&0x7fff:
vid_shiftmode = value;
vid_flag=1;
break;
case DMA_ADRH&0x7fff:
dma_adrh = value;
break;
case DMA_ADRM&0x7fff:
dma_adrm = value;
break;
case DMA_ADRL&0x7fff:
dma_adrl = value;
break;
}
return;
}
//Sound emu
if (address<0x900) {
#if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
static unsigned back_cycles=0;
static unsigned back_value=0;
static unsigned back_ctrl=0;
static unsigned new_value=0;
#endif
if (address<0x804)
waitstate+=1;
address&=3;
if (address==0) {
psgcontrol=value; //&15;
#if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
if ((M68KCONTEXT.cycles_counter+IO_CYCLE)==back_cycles) {
psg[back_ctrl]=back_value;
update_psg(new_value);
}
#endif
}else if (address==2 && psgcontrol<16) {
#if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
back_ctrl=psgcontrol;
back_value=psg[psgcontrol];
new_value=value;
#endif
update_psg(value);
}
#if defined(USE_FAME_CORE) && defined(USE_MOVEM_FAME_PATCH)
back_cycles=IO_CYCLE+M68KCONTEXT.cycles_counter;
#endif
return;
}
//Bus error?
if (address<0xb00) {
ExceptionGroup0(BUSERR, address|0xff8000, 0);
return;
}
//MFP emu
if (address<0x7c00) {
waitstate+=4;
switch(address) {
case MFP_AER&0x7fff:
mfp_aer = value;
break;
case MFP_DDR&0x7fff:
mfp_ddr = value;
break;
case MFP_IERA&0x7fff:
mfp_iera = value;
mfp_ipra &= mfp_iera;
break;
case MFP_IERB&0x7fff:
mfp_ierb = value;
mfp_iprb &= mfp_ierb;
break;
case MFP_IPRA&0x7fff:
mfp_ipra &= value;
break;
case MFP_IPRB&0x7fff:
mfp_iprb &= value;
break;
case MFP_ISRA&0x7fff:
mfp_isra &= value;
#ifndef USE_FAME_CORE
recalc_int = 1;
#endif
break;
case MFP_ISRB&0x7fff:
mfp_isrb &= value;
#ifndef USE_FAME_CORE
recalc_int = 1;
#endif
break;
case MFP_IMRA&0x7fff:
mfp_imra = value;
#ifndef USE_FAME_CORE
recalc_int = 1;
#endif
break;
case MFP_IMRB&0x7fff:
mfp_imrb = value;
#ifndef USE_FAME_CORE
recalc_int = 1;
#endif
break;
case MFP_IVR&0x7fff:
mfp_ivr = value;
break;
case MFP_TACR&0x7fff:
mfp_tacr = value&15;
#if defined(USE_FAME_CORE) && defined(USE_SHORT_SLICE)
if (mfp_ascale)
m68k_stop_emulating();
#endif
mfp_ascale = mfpcycletab[mfp_tacr];
break;
case MFP_TBCR&0x7fff:
mfp_tbcr = value&15;
#if defined(USE_FAME_CORE) && defined(USE_SHORT_SLICE)
if (mfp_bscale)
m68k_stop_emulating();
#endif
mfp_bscale = mfpcycletab[mfp_tbcr];
break;
case MFP_TCDCR&0x7fff:
mfp_tcdcr = value&0x77;
#if defined(USE_FAME_CORE) && defined(USE_SHORT_SLICE)
if (mfp_cscale || mfp_dscale)
m68k_stop_emulating();
#endif
mfp_cscale = mfpcycletab[mfp_tcdcr>>4];
mfp_dscale = mfpcycletab[mfp_tcdcr&7];
break;
case MFP_TADR&0x7fff:
if (value==0) mfp_tadr=256<<20; else mfp_tadr=value<<20;
if (mfp_ascale==0) mfp_acount=mfp_tadr;
break;
case MFP_TBDR&0x7fff:
if (value==0) mfp_tbdr=256<<20; else mfp_tbdr=value<<20;
if (mfp_bscale==0) mfp_bcount=mfp_tbdr;
break;
case MFP_TCDR&0x7fff:
if (value==0) mfp_tcdr=256<<20; else mfp_tcdr=value<<20;
if (mfp_cscale==0) mfp_ccount=mfp_tcdr;
break;
case MFP_TDDR&0x7fff:
if (value==0) mfp_tddr=256<<20; else mfp_tddr=value<<20;
if (mfp_dscale==0) mfp_dcount=mfp_tddr;
break;
case MFP_SCR&0x7fff:
mfp_scr = value;
break;
case MFP_UCR&0x7fff:
mfp_ucr = value;
break;
case MFP_RSR&0x7fff:
mfp_rsr = value;
break;
case MFP_TSR&0x7fff:
mfp_tsr = value;
break;
case MFP_UDR&0x7fff:
mfp_udr = value;
break;
}
return;
}
switch(address) {
case ACIA1_SR&0x7fff:
waitstate+=8;
acia1_cr = value;
break;
case ACIA1_DR&0x7fff:
waitstate+=8;
IkbdRecv (value);
break;
case ACIA2_SR&0x7fff:
waitstate+=8;
acia2_cr = value;
break;
case ACIA2_DR&0x7fff:
waitstate+=8;
break;
}
}
void DoIOWW(uint32 address, uint16 value)
{
if (address >= VID_COL0 && address <= VID_COL15) {
vid_col[(address & 0x1f) >> 1] = value&0x777;
vid_flag = 1;
return;
}
else
switch (address) {
case DMA_MODE:
dma_mode = value;
break;
case DMA_CAR:
waitstate+=4;
if (dma_mode & 0x10) dma_scr = value;
else if (dma_mode & 0x8) dma_car = value;
else {
switch (dma_mode & 0x6) {
case 0:
fdc_command = value;
FDCCommand ();
break;
case 2:
fdc_track = value;
break;
case 4:
fdc_sector = value;
break;
case 6:
fdc_data = value;
break;
}
}
break;
default:
DoIOWB(address, value>>8);
DoIOWB(address+1, value);
break;
}
}
void DoIOWL(uint32 address, uint32 value)
{
DoIOWW(address, value>>16);
DoIOWW(address+2, value);
}
static __inline__ void calculate_vid_adr(void)
{
unsigned yet=(vid_cycle[cyclenext-IO_CYCLE]-vid_adr_cycleyet)&(~3);
vid_adr+=yet;
vid_adr_cycleyet+=yet;
}
uint8 DoIORB(uint32 address)
{
address&=0x7fff;
//Video and dma emu
if (address<0x800) {
switch (address) {
case MEM_CONF&0x7fff:
return memconf;
case VID_BASEH&0x7fff:
return vid_baseh;
case VID_BASEM&0x7fff:
return vid_basem;
case VID_ADRH&0x7fff:
calculate_vid_adr();
return (unsigned char)(vid_adr>>16);
case VID_ADRM&0x7fff:
calculate_vid_adr();
return (unsigned char)(vid_adr>>8);
case VID_ADRL&0x7fff:
calculate_vid_adr();
return (unsigned char)(vid_adr);
case VID_SYNCMODE&0x7fff:
return vid_syncmode;
case VID_LINEWIDTH&0x7fff:
return 0xff;
case VID_SHIFTMODE&0x7fff:
return vid_shiftmode;
case DMA_ADRH&0x7fff:
return dma_adrh;
case DMA_ADRM&0x7fff:
return dma_adrm;
case DMA_ADRL&0x7fff:
return dma_adrl;
}
return VALUE_OPEN;
}
//Sound emu
if (address<0x900) {
address&=3;
if (!address)
{
waitstate+=4;
if (psgcontrol>=16) return 0xff;
return psg[psgcontrol];
}
else if (address<4)
waitstate++;
return VALUE_OPEN;
}
//Bus error?
if (address<0xb00) {
ExceptionGroup0(BUSERR, address|0xff8000, 0);
return VALUE_OPEN;
}
//MFP emu
if (address<0x7c00) {
waitstate+=4;
switch(address) {
case MFP_GPIP&0x7fff:
return mfp_gpip;
case MFP_AER&0x7fff:
return mfp_aer;
case MFP_DDR&0x7fff:
return mfp_ddr;
case MFP_IERA&0x7fff:
return mfp_iera;
case MFP_IERB&0x7fff:
return mfp_ierb;
case MFP_IPRA&0x7fff:
return mfp_ipra;
case MFP_IPRB&0x7fff:
return mfp_iprb;
case MFP_ISRA&0x7fff:
return mfp_isra;
case MFP_ISRB&0x7fff:
return mfp_isrb;
case MFP_IMRA&0x7fff:
return mfp_imra;
case MFP_IMRB&0x7fff:
return mfp_imrb;
case MFP_IVR&0x7fff:
return mfp_ivr;
case MFP_TACR&0x7fff:
return mfp_tacr;
case MFP_TBCR&0x7fff:
return mfp_tbcr;
case MFP_TCDCR&0x7fff:
return mfp_tcdcr;
case MFP_TADR&0x7fff:
return (mfp_acount+0xfffff)>>20;
case MFP_TBDR&0x7fff:
return (mfp_bcount+0xfffff)>>20;
case MFP_TCDR&0x7fff:
return (mfp_ccount+0xfffff)>>20;
case MFP_TDDR&0x7fff:
return (mfp_dcount+0xfffff)>>20;
case MFP_SCR&0x7fff:
return mfp_scr;
case MFP_UCR&0x7fff:
return mfp_ucr;
case MFP_RSR&0x7fff:
return mfp_rsr;
case MFP_TSR&0x7fff:
return mfp_tsr;
case MFP_UDR&0x7fff:
return mfp_udr;
}
return VALUE_OPEN;
}
//Acia emu
switch(address) {
case ACIA1_SR&0x7fff:
waitstate+=8;
return 2 | acia1_sr;
case ACIA1_DR&0x7fff:
waitstate+=8;
if (!(acia1_cr & 0x20)) {acia1_sr&=0x7e; mfp_gpip|=0x10;}
return acia1_dr;
case ACIA2_SR&0x7fff:
waitstate+=8;
return 2;
case ACIA2_DR&0x7fff:
waitstate+=8;
return 1;
}
return VALUE_OPEN;
}
uint16 DoIORW(uint32 address)
{
if (address >= VID_COL0 && address <= VID_COL15) {
return vid_col[(address & 0x1f) >> 1];
}
switch (address) {
case DMA_SR:
return dma_sr;
case DMA_CAR:
waitstate+=4;
if (dma_mode & 0x10) return dma_scr;
else if (dma_mode & 0x8) return dma_car;
else {
switch (dma_mode & 0x6) {
case 0:
if (!fdc_int) mfp_gpip |= 0x20;
return fdc_status;
case 2:
return fdc_track;
case 4:
return fdc_sector;
case 6:
return fdc_data;
}
return 0;
}
default:
return (((uint32)DoIORB(address))<<8)+DoIORB(address+1);
}
}
uint32 DoIORL(uint32 address)
{
return (((uint32)DoIORW(address))<<16)+DoIORW(address+2);
}

Wyświetl plik

@ -0,0 +1,304 @@
/*
* Castaway
* (C) 1994 - 2002 Martin Doering, Joachim Hoenig
*
* This file is distributed under the GPL, version 2 or at your
* option any later version. See doc/license.txt for details.
*/
#ifndef STH
#define STH
#define MAX_DISC_SIZE 1050*1024
/*
* I/O register addresses
*/
#define MEM_CONF 0xff8001
#define VID_BASEH 0xff8201
#define VID_BASEM 0xff8203
#define VID_ADRH 0xff8205
#define VID_ADRM 0xff8207
#define VID_ADRL 0xff8209
#define VID_SYNCMODE 0xff820a
#define VID_BASEL 0xff820d
#define VID_LINEWIDTH 0xff820f
#define VID_COL0 0xff8240
#define VID_COL1 0xff8242
#define VID_COL2 0xff8244
#define VID_COL3 0xff8246
#define VID_COL4 0xff8248
#define VID_COL5 0xff824a
#define VID_COL6 0xff824c
#define VID_COL7 0xff824e
#define VID_COL8 0xff8250
#define VID_COL9 0xff8252
#define VID_COL10 0xff8254
#define VID_COL11 0xff8256
#define VID_COL12 0xff8258
#define VID_COL13 0xff825a
#define VID_COL14 0xff825c
#define VID_COL15 0xff825e
#define VID_SHIFTMODE 0xff8260
#define DMA_CAR 0xff8604
#define DMA_SCR 0xff8604
#define DMA_SR 0xff8606
#define DMA_MODE 0xff8606
#define DMA_ADRH 0xff8609
#define DMA_ADRM 0xff860b
#define DMA_ADRL 0xff860d
#define SND_RS 0xff8800
#define SND_WD 0xff8802
#define BLT_HFT 0xff8a00
#define BLT_SXINC 0xff8a20
#define BLT_SYINC 0xff8a22
#define BLT_SADR 0xff8a24
#define BLT_END1 0xff8a28
#define BLT_END2 0xff8a2a
#define BLT_END3 0xff8a2c
#define BLT_DXINC 0xff8a2e
#define BLT_DYINC 0xff8a30
#define BLT_DADR 0xff8a32
#define BLT_XCNT 0xff8a36
#define BLT_YCNT 0xff8a38
#define BLT_HOP 0xff8a3a
#define BLT_OP 0xff8a3b
#define BLT_STAT 0xff8a3c
#define BLT_SKEW 0xff8a3d
#define MFP_GPIP 0xfffa01
#define MFP_AER 0xfffa03
#define MFP_DDR 0xfffa05
#define MFP_IERA 0xfffa07
#define MFP_IERB 0xfffa09
#define MFP_IPRA 0xfffa0b
#define MFP_IPRB 0xfffa0d
#define MFP_ISRA 0xfffa0f
#define MFP_ISRB 0xfffa11
#define MFP_IMRA 0xfffa13
#define MFP_IMRB 0xfffa15
#define MFP_IVR 0xfffa17
#define MFP_TACR 0xfffa19
#define MFP_TBCR 0xfffa1b
#define MFP_TCDCR 0xfffa1d
#define MFP_TADR 0xfffa1f
#define MFP_TBDR 0xfffa21
#define MFP_TCDR 0xfffa23
#define MFP_TDDR 0xfffa25
#define MFP_SCR 0xfffa27
#define MFP_UCR 0xfffa29
#define MFP_RSR 0xfffa2b
#define MFP_TSR 0xfffa2d
#define MFP_UDR 0xfffa2f
#define ACIA1_SR 0xfffc00
#define ACIA1_DR 0xfffc02
#define ACIA2_SR 0xfffc04
#define ACIA2_DR 0xfffc06
#define RTC_SECL 0xfffc21
#define RTC_SECH 0xfffc23
#define RTC_MINL 0xfffc25
#define RTC_MINH 0xfffc27
#define RTC_HRSL 0xfffc29
#define RTC_HRSH 0xfffc2b
#define RTC_DAY 0xfffc2d
#define RTC_DAYL 0xfffc2f
#define RTC_DAYH 0xfffc31
#define RTC_MONL 0xfffc33
#define RTC_MONH 0xfffc35
#define RTC_YRL 0xfffc37
#define RTC_YRH 0xfffc39
#define RTC_RES1 0xfffc3b
#define RTC_RES2 0xfffc3d
#define RTC_RES3 0xfffc3f
#define IBS 32
#define OBS 64
/*
* ROM/Cartridge file names
*/
extern char cartridge[80], rom[80];
/*
* I/O register values
*/
extern uint8 memconf;
extern uint8 mfp_gpip, mfp_aer, mfp_ddr, mfp_iera, mfp_ierb, mfp_ipra, mfp_iprb,
mfp_isra, mfp_isrb, mfp_imra, mfp_imrb, mfp_ivr, mfp_tacr,
mfp_tbcr, mfp_tcdcr, mfp_scr, mfp_ucr, mfp_rsr, mfp_tsr, mfp_udr;
//Mfp delay timer variables
extern int32 mfp_reg[12];
#define mfp_tadr mfp_reg[0]
#define mfp_tbdr mfp_reg[1]
#define mfp_tcdr mfp_reg[2]
#define mfp_tddr mfp_reg[3]
#define mfp_acount mfp_reg[4]
#define mfp_bcount mfp_reg[5]
#define mfp_ccount mfp_reg[6]
#define mfp_dcount mfp_reg[7]
#define mfp_ascale mfp_reg[8]
#define mfp_bscale mfp_reg[9]
#define mfp_cscale mfp_reg[10]
#define mfp_dscale mfp_reg[11]
extern uint8 acia1_cr, acia1_sr, acia1_dr, acia2_cr, acia2_sr,
acia2_dr;
extern int checkedsample;
extern int checkedsound;
//Video shifter
extern uint32 vid_adr;
extern uint8 vid_baseh, vid_basem;
extern uint32 vid_mem;
extern uint8 vid_syncmode, vid_shiftmode;
extern int16 vid_col[];
extern int vid_flag;
extern uint16 dma_car, dma_scr, dma_sr, dma_mode;
extern uint8 dma_adrh, dma_adrm, dma_adrl;
extern const int32 mfpcycletab[16];
extern uint32 psg[26];
//extern unsigned char sample[10000];
#define phase0 psg[16]
#define phase1 psg[17]
#define phase2 psg[18]
#define phase3 psg[19]
#define psg_epos psg[20]
#define psgcontrol psg[21]
#define phase4 psg[22]
#define nrand psg[23]
#define samppos psg[24]
#define lastpsg psg[25]
/* ikbd.c */
extern void IkbdLoop(void);
extern void IkbdRecv(uint8);
extern void IkbdSend(uint8);
extern void IkbdWriteBuffer(void); /* write byte IKBD -> ST */
extern void IkbdKeyPress(unsigned short keysym); /* key press */
extern void IkbdKeyRelease(unsigned short keysym); /* key release */
extern void IkbdMousePress(int); /* mouse button press */
extern void IkbdMouseRelease(int); /* mouse button release */
extern void IkbdMouseMotion(int x, int y); /* mouse movement */
//extern void IkbdMouseMotion(int x, int y, int dx, int dy); /* mouse movement */
extern void joystickevent(int joystate);
extern void IkbdReset(void);
/* fdc.c */
extern unsigned char fdc_data, fdc_track, fdc_sector,
fdc_status, fdc_command, fdc_int;
extern unsigned char disk_ejected[2];
extern unsigned char disk_changed[2];
struct Disk {
int file;
char name[80];
int head;
int sides;
int tracks;
int sectors;
int secsize;
int disksize;
};
extern struct Disk disk[2];
extern int FDCInit(int i);
extern void FDCCommand(void);
void FDCeject(int num);
int unzipdisk(unsigned char *RomPath,unsigned char *buf);
/* blitter.c */
extern uint16 blt_halftone[16];
extern int16 blt_src_x_inc, blt_src_y_inc;
extern uint32 blt_src_addr;
extern int16 blt_end_1, blt_end_2, blt_end_3;
extern int16 blt_dst_x_inc, blt_dst_y_inc;
extern uint32 blt_dst_addr;
extern uint16 blt_x_cnt, blt_y_cnt;
extern int8 blt_hop, blt_op, blt_status, blt_skew;
extern void bitblt(void);
/* init.c */
extern int Init();
/* main.c */
extern unsigned ips;
/* mem.c */
extern int MemInit(void);
extern void MemTableSet(uint32 base, uint32 size,
void (*setbyte)(uint32, uint8),
void (*setword)(uint32, uint16),
void (*setlong)(uint32, uint32 ),
uint8 (*getbyte)(uint32),
uint16 (*getword)(uint32),
uint32 (*getlong)(uint32) );
extern void RamSetB(uint32, uint8);
extern void RamSetW(uint32, uint16);
extern void RamSetL(uint32, uint32 );
extern uint8 RamGetB(uint32);
extern uint16 RamGetW(uint32);
extern uint32 RamGetL(uint32);
/*
* Video shift modes
*/
#define COL4 0
#define COL2 1
#define MONO 2
extern int display_mode;
/*
* Read/Write IO Registers (return value != 0 if bus error)
*/
uint8 DoIORB(uint32 address);
uint16 DoIORW(uint32 address);
uint32 DoIORL(uint32 address);
void DoIOWB(uint32 address, uint8 value);
void DoIOWW(uint32 address, uint16 value);
void DoIOWL(uint32 address, uint32 value);
void IOInit(void);
struct _mouse {
char buttons; /* real buttons */
char stbuttons; /* buttons as known to st */
int xscale, yscale;
int xmax, ymax;
int xkcm, ykcm;
int xth, yth;
int x, y; /* real mouse position */
int stx, sty; /* mouse position st */
int button_action;
int mode;
int yinv;
int flag;
};
struct _joystick {
int mode;
int rate;
int state0; /* joystick 0 state */
int state1; /* joystick 1 state */
int rx, ry, tx, ty, vx, vy;
};
extern struct _mouse mouse;
extern struct _joystick joystick;
void Ikbd_Reset(void);
void IkbdJoystickChange(int number, uint8 state);
int unzipdisk(unsigned char *RomPath,unsigned char *buf);
void reset_st_video(void);
#endif

Wyświetl plik

@ -0,0 +1,18 @@
static const int LogTable[256] = {
0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,
4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,
5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,
7,8,8,8,8,8,8,9,9,9,9,9,10,10,10,10,
10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,
15,15,15,15,16,16,16,17,17,17,18,18,19,19,19,20,
20,21,21,21,22,22,23,23,24,24,25,25,26,26,27,27,
28,28,29,30,30,31,31,32,33,33,34,35,35,36,37,38,
38,39,40,41,42,42,43,44,45,46,47,48,49,50,51,52,
53,54,55,56,57,58,60,61,62,63,65,66,67,69,70,71,
73,74,76,77,79,80,82,84,85,87,89,91,92,94,96,98,
100,102,104,106,108,111,113,115,117,120,122,125,127,130,132,135,
138,140,143,146,149,152,155,158,161,164,168,171,175,178,182,185,
189,193,197,201,205,209,213,217,221,226,230,235,240,245,250,255
};

Wyświetl plik

@ -0,0 +1,3 @@
static const int LogTable16[16] = {
0,0,1,1,2,4,6,9,14,22,33,50,75,113,170,255
};

Wyświetl plik

@ -0,0 +1,130 @@
static const char MixTable[2048] = {
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x82,0x82,0x83,0x83,0x83,
0x84,0x84,0x84,0x85,0x85,0x85,0x85,0x86,0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,
0x88,0x89,0x89,0x89,0x8A,0x8A,0x8A,0x8B,0x8B,0x8B,0x8B,0x8C,0x8C,0x8C,0x8D,0x8D,
0x8D,0x8E,0x8E,0x8E,0x8E,0x8F,0x8F,0x8F,0x90,0x90,0x90,0x91,0x91,0x91,0x91,0x92,
0x92,0x92,0x93,0x93,0x93,0x94,0x94,0x94,0x94,0x95,0x95,0x95,0x96,0x96,0x96,0x97,
0x97,0x97,0x97,0x98,0x98,0x98,0x99,0x99,0x99,0x9A,0x9A,0x9A,0x9A,0x9B,0x9B,0x9B,
0x9C,0x9C,0x9C,0x9D,0x9D,0x9D,0x9D,0x9E,0x9E,0x9E,0x9F,0x9F,0x9F,0xA0,0xA0,0xA0,
0xA0,0xA1,0xA1,0xA1,0xA2,0xA2,0xA2,0xA3,0xA3,0xA3,0xA3,0xA4,0xA4,0xA4,0xA5,0xA5,
0xA5,0xA6,0xA6,0xA6,0xA6,0xA7,0xA7,0xA7,0xA8,0xA8,0xA8,0xA9,0xA9,0xA9,0xA9,0xAA,
0xAA,0xAA,0xAB,0xAB,0xAB,0xAC,0xAC,0xAC,0xAC,0xAD,0xAD,0xAD,0xAE,0xAE,0xAE,0xAF,
0xAF,0xAF,0xAF,0xB0,0xB0,0xB0,0xB1,0xB1,0xB1,0xB2,0xB2,0xB2,0xB2,0xB3,0xB3,0xB3,
0xB4,0xB4,0xB4,0xB5,0xB5,0xB5,0xB5,0xB6,0xB6,0xB6,0xB7,0xB7,0xB7,0xB8,0xB8,0xB8,
0xB8,0xB9,0xB9,0xB9,0xBA,0xBA,0xBA,0xBB,0xBB,0xBB,0xBB,0xBC,0xBC,0xBC,0xBD,0xBD,
0xBD,0xBE,0xBE,0xBE,0xBE,0xBF,0xBF,0xBF,0xC0,0xC0,0xC0,0xC1,0xC1,0xC1,0xC1,0xC2,
0xC2,0xC2,0xC3,0xC3,0xC3,0xC4,0xC4,0xC4,0xC4,0xC5,0xC5,0xC5,0xC6,0xC6,0xC6,0xC7,
0xC7,0xC7,0xC7,0xC8,0xC8,0xC8,0xC9,0xC9,0xC9,0xCA,0xCA,0xCA,0xCA,0xCB,0xCB,0xCB,
0xCC,0xCC,0xCC,0xCD,0xCD,0xCD,0xCD,0xCE,0xCE,0xCE,0xCF,0xCF,0xCF,0xD0,0xD0,0xD0,
0xD0,0xD1,0xD1,0xD1,0xD2,0xD2,0xD2,0xD3,0xD3,0xD3,0xD3,0xD4,0xD4,0xD4,0xD5,0xD5,
0xD5,0xD6,0xD6,0xD6,0xD6,0xD7,0xD7,0xD7,0xD8,0xD8,0xD8,0xD9,0xD9,0xD9,0xD9,0xDA,
0xDA,0xDA,0xDB,0xDB,0xDB,0xDC,0xDC,0xDC,0xDC,0xDD,0xDD,0xDD,0xDE,0xDE,0xDE,0xDF,
0xDF,0xDF,0xDF,0xE0,0xE0,0xE0,0xE1,0xE1,0xE1,0xE2,0xE2,0xE2,0xE2,0xE3,0xE3,0xE3,
0xE4,0xE4,0xE4,0xE5,0xE5,0xE5,0xE5,0xE6,0xE6,0xE6,0xE7,0xE7,0xE7,0xE8,0xE8,0xE8,
0xE8,0xE9,0xE9,0xE9,0xEA,0xEA,0xEA,0xEB,0xEB,0xEB,0xEB,0xEC,0xEC,0xEC,0xED,0xED,
0xED,0xEE,0xEE,0xEE,0xEE,0xEF,0xEF,0xEF,0xF0,0xF0,0xF0,0xF1,0xF1,0xF1,0xF1,0xF2,
0xF2,0xF2,0xF3,0xF3,0xF3,0xF4,0xF4,0xF4,0xF4,0xF5,0xF5,0xF5,0xF6,0xF6,0xF6,0xF7,
0xF7,0xF7,0xF7,0xF8,0xF8,0xF8,0xF9,0xF9,0xF9,0xFA,0xFA,0xFA,0xFA,0xFB,0xFB,0xFB,
0xFC,0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x04,0x04,
0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,
0x09,0x09,0x0A,0x0A,0x0A,0x0B,0x0B,0x0B,0x0C,0x0C,0x0C,0x0C,0x0D,0x0D,0x0D,0x0E,
0x0E,0x0E,0x0F,0x0F,0x0F,0x0F,0x10,0x10,0x10,0x11,0x11,0x11,0x12,0x12,0x12,0x12,
0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x17,
0x18,0x18,0x18,0x18,0x19,0x19,0x19,0x1A,0x1A,0x1A,0x1B,0x1B,0x1B,0x1B,0x1C,0x1C,
0x1C,0x1D,0x1D,0x1D,0x1E,0x1E,0x1E,0x1E,0x1F,0x1F,0x1F,0x20,0x20,0x20,0x21,0x21,
0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x24,0x25,0x25,0x25,0x26,
0x26,0x26,0x27,0x27,0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x29,0x2A,0x2A,0x2A,0x2A,
0x2B,0x2B,0x2B,0x2C,0x2C,0x2C,0x2D,0x2D,0x2D,0x2D,0x2E,0x2E,0x2E,0x2F,0x2F,0x2F,
0x30,0x30,0x30,0x30,0x31,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x33,0x34,0x34,
0x34,0x35,0x35,0x35,0x36,0x36,0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,0x39,0x39,
0x39,0x39,0x3A,0x3A,0x3A,0x3B,0x3B,0x3B,0x3C,0x3C,0x3C,0x3C,0x3D,0x3D,0x3D,0x3E,
0x3E,0x3E,0x3F,0x3F,0x3F,0x3F,0x40,0x40,0x40,0x41,0x41,0x41,0x42,0x42,0x42,0x42,
0x43,0x43,0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,
0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x4A,0x4A,0x4A,0x4B,0x4B,0x4B,0x4B,0x4C,0x4C,
0x4C,0x4D,0x4D,0x4D,0x4E,0x4E,0x4E,0x4E,0x4F,0x4F,0x4F,0x50,0x50,0x50,0x51,0x51,
0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x54,0x54,0x55,0x55,0x55,0x56,
0x56,0x56,0x57,0x57,0x57,0x57,0x58,0x58,0x58,0x59,0x59,0x59,0x5A,0x5A,0x5A,0x5A,
0x5B,0x5B,0x5B,0x5C,0x5C,0x5C,0x5D,0x5D,0x5D,0x5D,0x5E,0x5E,0x5E,0x5F,0x5F,0x5F,
0x60,0x60,0x60,0x60,0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63,0x63,0x64,0x64,
0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,0x69,0x69,
0x69,0x69,0x6A,0x6A,0x6A,0x6B,0x6B,0x6B,0x6C,0x6C,0x6C,0x6C,0x6D,0x6D,0x6D,0x6E,
0x6E,0x6E,0x6F,0x6F,0x6F,0x6F,0x70,0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x72,
0x73,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,
0x78,0x78,0x78,0x78,0x79,0x79,0x79,0x7A,0x7A,0x7A,0x7B,0x7B,0x7B,0x7B,0x7C,0x7C,
0x7C,0x7D,0x7D,0x7D,0x7E,0x7E,0x7E,0x7E,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F
};

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,479 @@
/** EMULib Emulation Library *********************************/
/** **/
/** Sound.c **/
/** **/
/** This file file implements core part of the sound API **/
/** and functions needed to log soundtrack into a MIDI **/
/** file. See Sound.h for declarations. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2003 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "Sound.h"
#include <stdio.h>
#include <string.h>
#ifdef UNIX
#include <unistd.h>
#endif
typedef unsigned char byte;
typedef unsigned short word;
struct SndDriverStruct SndDriver =
{
(void (*)(int,int))0,
(void (*)(int,int))0,
(void (*)(int,int))0,
(void (*)(int,int,int))0,
(void (*)(int,const signed char *,int,int))0
};
#ifdef unused
static const struct { byte Note;word Wheel; } Freqs[4096] =
{
#include "MIDIFreq.h"
};
#endif
static const int Programs[5] =
{
80, /* SND_MELODIC/SND_RECTANGLE */
80, /* SND_TRIANGLE */
122, /* SND_NOISE */
122, /* SND_PERIODIC */
80 /* SND_WAVE */
};
#ifdef unused
static struct
{
int Type;
int Note;
int Pitch;
int Level;
} CH[MIDI_CHANNELS];
static const char *LogName = 0;
static int Logging = MIDI_OFF;
static int TickCount = 0;
static int LastMsg = -1;
static FILE *MIDIOut = 0;
static void MIDISound(int Channel,int Freq,int Volume);
static void MIDISetSound(int Channel,int Type);
static void MIDIDrum(int Type,int Force);
static void MIDIMessage(byte D0,byte D1,byte D2);
static void NoteOn(byte Channel,byte Note,byte Level);
static void NoteOff(byte Channel);
static void WriteDelta(void);
static void WriteTempo(int Freq);
/** SHIFT() **************************************************/
/** Make MIDI channel#10 last, as it is normally used for **/
/** percussion instruments only and doesn't sound nice. **/
/*************************************************************/
#define SHIFT(Ch) (Ch==15? 9:Ch>8? Ch+1:Ch)
#endif
/** Sound() **************************************************/
/** Generate sound of given frequency (Hz) and volume **/
/** (0..255) via given channel. Setting Freq=0 or Volume=0 **/
/** turns sound off. **/
/*************************************************************/
void Sound(int Channel,int Freq,int Volume)
{
if(Channel<0) return;
Freq = Freq<0? 0:Freq;
Volume = Volume<0? 0:Volume>255? 255:Volume;
/* Call sound driver if present */
if(SndDriver.Sound) (*SndDriver.Sound)(Channel,Freq,Volume);
#ifdef unused
/* Log sound to MIDI file */
MIDISound(Channel,Freq,Volume);
#endif
}
/** Drum() ***************************************************/
/** Hit a drum of given type with given force (0..255). **/
/** MIDI drums can be used by ORing their numbers with **/
/** SND_MIDI. **/
/*************************************************************/
void Drum(int Type,int Force)
{
Force = Force<0? 0:Force>255? 255:Force;
if(SndDriver.Drum) (*SndDriver.Drum)(Type,Force);
#ifdef unused
/* Log drum to MIDI file */
MIDIDrum(Type,Force);
#endif
}
/** SetSound() ***********************************************/
/** Set sound type at a given channel. MIDI instruments can **/
/** be set directly by ORing their numbers with SND_MIDI. **/
/*************************************************************/
void SetSound(int Channel,int Type)
{
if(Channel<0) return;
if(SndDriver.SetSound) (*SndDriver.SetSound)(Channel,Type);
#ifdef unused
/* Log instrument change to MIDI file */
MIDISetSound(Channel,Type);
#endif
}
/** SetChannels() ********************************************/
/** Set master volume (0..255) and switch channels on/off. **/
/** Each channel N has corresponding bit 2^N in Switch. Set **/
/** or reset this bit to turn the channel on or off. **/
/*************************************************************/
void SetChannels(int Volume,int Switch)
{
Volume = Volume<0? 0:Volume>255? 255:Volume;
if(SndDriver.SetChannels) (*SndDriver.SetChannels)(Volume,Switch);
}
/** SetWave() ************************************************/
/** Set waveform for a given channel. The channel will be **/
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
/** waveform to be an instrument or set it to the waveform **/
/** own playback rate. **/
/*************************************************************/
void SetWave(int Channel,const signed char *Data,int Length,int Rate)
{
if((Channel<0)||(Length<=0)) return;
if(SndDriver.SetWave) (*SndDriver.SetWave)(Channel,Data,Length,Rate);
#ifdef unused
/* Log instrument change to MIDI file */
MIDISetSound(Channel,Rate? -1:SND_MELODIC);
#endif
}
#ifdef unused
/** InitMIDI() ***********************************************/
/** Initialize soundtrack logging into MIDI file FileName. **/
/** Repeated calls to InitMIDI() will close current MIDI **/
/** file and continue logging into a new one. **/
/*************************************************************/
void InitMIDI(const char *FileName)
{
int WasLogging,J;
/* Must pass a name! */
if(!FileName) return;
/* Memorize logging status */
WasLogging=Logging;
/* If MIDI logging in progress, close current file */
if(MIDIOut) TrashMIDI();
/* Clear instrument types */
for(J=0;J<MIDI_CHANNELS;J++) CH[J].Type=-1;
/* Set log file name and ticks/second parameter, no logging yet */
//LogName = FileName;
Logging = MIDI_OFF;
LastMsg = -1;
TickCount = 0;
MIDIOut = 0;
/* If was logging, restart */
if(WasLogging) MIDILogging(MIDI_ON);
}
/** TrashMIDI() **********************************************/
/** Finish logging soundtrack and close the MIDI file. **/
/*************************************************************/
void TrashMIDI(void)
{
long Length;
int J;
/* If not logging, drop out */
if(!MIDIOut) return;
/* Turn sound off */
for(J=0;J<MIDI_CHANNELS;J++) NoteOff(J);
/* End of track */
MIDIMessage(0xFF,0x2F,0x00);
/* Put track length in file */
fseek(MIDIOut,0,SEEK_END);
Length=ftell(MIDIOut)-22;
fseek(MIDIOut,18,SEEK_SET);
fputc((Length>>24)&0xFF,MIDIOut);
fputc((Length>>16)&0xFF,MIDIOut);
fputc((Length>>8)&0xFF,MIDIOut);
fputc(Length&0xFF,MIDIOut);
/* Done logging */
fclose(MIDIOut);
Logging = MIDI_OFF;
LastMsg = -1;
TickCount = 0;
MIDIOut = 0;
}
/** MIDILogging() ********************************************/
/** Turn soundtrack logging on/off and return its current **/
/** status. Possible values of Switch are MIDI_OFF (turn **/
/** logging off), MIDI_ON (turn logging on), MIDI_TOGGLE **/
/** (toggle logging), and MIDI_QUERY (just return current **/
/** state of logging). **/
/*************************************************************/
int MIDILogging(int Switch)
{
static const char MThd[] = "MThd\0\0\0\006\0\0\0\1";
/* ID DataLen Fmt Trks */
static const char MTrk[] = "MTrk\0\0\0\0";
/* ID TrkLen */
int J,I;
/* Toggle logging if requested */
if(Switch==MIDI_TOGGLE) Switch=!Logging;
if((Switch==MIDI_ON)||(Switch==MIDI_OFF))
if(Switch^Logging)
{
/* When turning logging off, silence all channels */
if(!Switch&&MIDIOut)
for(J=0;J<MIDI_CHANNELS;J++) NoteOff(J);
/* When turning logging on, open MIDI file */
if(Switch&&!MIDIOut&&LogName)
{
/* No messages have been sent yet */
LastMsg=-1;
/* Clear all storage */
for(J=0;J<MIDI_CHANNELS;J++)
CH[J].Note=CH[J].Pitch=CH[J].Level=-1;
/* Open new file and write out the header */
MIDIOut=fopen(LogName,"wb");
if(!MIDIOut) return(MIDI_OFF);
if(fwrite(MThd,1,12,MIDIOut)!=12)
{ fclose(MIDIOut);MIDIOut=0;return(MIDI_OFF); }
fputc((MIDI_DIVISIONS>>8)&0xFF,MIDIOut);
fputc(MIDI_DIVISIONS&0xFF,MIDIOut);
if(fwrite(MTrk,1,8,MIDIOut)!=8)
{ fclose(MIDIOut);MIDIOut=0;return(MIDI_OFF); }
/* Write out the tempo */
WriteTempo(MIDI_DIVISIONS);
}
/* Turn logging off on failure to open MIDIOut */
if(!MIDIOut) Switch=MIDI_OFF;
/* Assign new switch value */
Logging=Switch;
/* If switching logging on... */
if(Switch)
{
/* Start logging without a pause */
TickCount=0;
/* Write instrument changes */
for(J=0;J<MIDI_CHANNELS;J++)
if((CH[J].Type>=0)&&(CH[J].Type&0x10000))
{
I=CH[J].Type&~0x10000;
CH[J].Type=-1;
MIDISetSound(J,I);
}
}
}
/* Return current logging status */
return(Logging);
}
/** MIDITicks() **********************************************/
/** Log N 1ms MIDI ticks. **/
/*************************************************************/
void MIDITicks(int N)
{
if(Logging&&MIDIOut&&(N>0)) TickCount+=N;
}
/** MIDISound() **********************************************/
/** Set sound frequency (Hz) and volume (0..255) for a **/
/** given channel. **/
/*************************************************************/
void MIDISound(int Channel,int Freq,int Volume)
{
int MIDIVolume,MIDINote,MIDIWheel;
/* If logging off, file closed, or invalid channel, drop out */
if(!Logging||!MIDIOut||(Channel>=MIDI_CHANNELS-1)||(Channel<0)) return;
/* Frequency must be in range */
if((Freq<MIDI_MINFREQ)||(Freq>MIDI_MAXFREQ)) Freq=0;
/* Volume must be in range */
if(Volume<0) Volume=0; else if(Volume>255) Volume=255;
/* Instrument number must be valid */
if(CH[Channel].Type<0) Freq=0;
if(!Volume||!Freq) NoteOff(Channel);
else
{
/* SND_TRIANGLE is twice quieter than SND_MELODIC */
if(CH[Channel].Type==SND_TRIANGLE) Volume=(Volume+1)/2;
/* Compute MIDI note parameters */
MIDIVolume = (127*Volume+128)/255;
MIDINote = Freqs[Freq/3].Note;
MIDIWheel = Freqs[Freq/3].Wheel;
/* Play new note */
NoteOn(Channel,MIDINote,MIDIVolume);
/* Change pitch */
if(CH[Channel].Pitch!=MIDIWheel)
{
MIDIMessage(0xE0+SHIFT(Channel),MIDIWheel&0x7F,(MIDIWheel>>7)&0x7F);
CH[Channel].Pitch=MIDIWheel;
}
}
}
/** MIDISetSound() *******************************************/
/** Set sound type for a given channel. **/
/*************************************************************/
void MIDISetSound(int Channel,int Type)
{
/* Channel must be valid */
if((Channel>=MIDI_CHANNELS-1)||(Channel<0)) return;
/* If instrument changed... */
if(CH[Channel].Type!=Type)
{
/* If logging off or file closed, drop out */
if(!Logging||!MIDIOut) CH[Channel].Type=Type|0x10000;
else
{
CH[Channel].Type=Type;
if(Type<0) NoteOff(Channel);
else
{
Type=Type&SND_MIDI? (Type&0x7F):Programs[Type%5];
MIDIMessage(0xC0+SHIFT(Channel),Type,255);
}
}
}
}
/** MIDIDrum() ***********************************************/
/** Hit a drum of a given type with given force. **/
/*************************************************************/
void MIDIDrum(int Type,int Force)
{
/* If logging off or invalid channel, drop out */
if(!Logging||!MIDIOut) return;
/* The only non-MIDI drum is a click ("Low Wood Block") */
Type=Type&DRM_MIDI? (Type&0x7F):77;
MIDIMessage(0x99,Type,(Force&0xFF)/2);
}
/** MIDIMessage() ********************************************/
/** Write out a MIDI message. **/
/*************************************************************/
void MIDIMessage(byte D0,byte D1,byte D2)
{
/* Write number of ticks that passed */
WriteDelta();
/* Write out the command */
if(D0!=LastMsg) { LastMsg=D0;fputc(D0,MIDIOut); }
/* Write out the arguments */
if(D1<128)
{
fputc(D1,MIDIOut);
if(D2<128) fputc(D2,MIDIOut);
}
}
/** NoteOn() *************************************************/
/** Turn on a note on a given channel. **/
/*************************************************************/
void NoteOn(byte Channel,byte Note,byte Level)
{
Note = Note>0x7F? 0x7F:Note;
Level = Level>0x7F? 0x7F:Level;
if((CH[Channel].Note!=Note)||(CH[Channel].Level!=Level))
{
if((CH[Channel].Note>=0)&&(CH[Channel].Note!=Note)) NoteOff(Channel);
MIDIMessage(0x90+SHIFT(Channel),Note,Level);
CH[Channel].Note=Note;
CH[Channel].Level=Level;
}
}
/** NoteOff() ************************************************/
/** Turn off a note on a given channel. **/
/*************************************************************/
void NoteOff(byte Channel)
{
if(CH[Channel].Note>=0)
{
MIDIMessage(0x80+SHIFT(Channel),CH[Channel].Note,127);
CH[Channel].Note=-1;
}
}
/** WriteDelta() *********************************************/
/** Write number of ticks since the last MIDI command and **/
/** reset the counter. **/
/*************************************************************/
void WriteDelta(void)
{
if(TickCount<128) fputc(TickCount,MIDIOut);
else
{
if(TickCount<128*128)
{
fputc((TickCount>>7)|0x80,MIDIOut);
fputc(TickCount&0x7F,MIDIOut);
}
else
{
fputc(((TickCount>>14)&0x7F)|0x80,MIDIOut);
fputc(((TickCount>>7)&0x7F)|0x80,MIDIOut);
fputc(TickCount&0x7F,MIDIOut);
}
}
TickCount=0;
}
/** WriteTempo() *********************************************/
/** Write out soundtrack tempo (Hz). **/
/*************************************************************/
void WriteTempo(int Freq)
{
int J;
J=500000*MIDI_DIVISIONS*2/Freq;
WriteDelta();
fputc(0xFF,MIDIOut);
fputc(0x51,MIDIOut);
fputc(0x03,MIDIOut);
fputc((J>>16)&0xFF,MIDIOut);
fputc((J>>8)&0xFF,MIDIOut);
fputc(J&0xFF,MIDIOut);
}
#endif

Wyświetl plik

@ -0,0 +1,152 @@
/** EMULib Emulation Library *********************************/
/** **/
/** Sound.h **/
/** **/
/** This file defines standard sound generation API and **/
/** functions needed to log soundtrack into a MIDI file. **/
/** See Sound.c and the sound drivers for the code. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2003 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef SOUND_H
#define SOUND_H
/* SetSound() arguments: */
#define SND_MELODIC 0 /* Melodic sound (default) */
#define SND_RECTANGLE 0 /* Rectangular wave */
#define SND_TRIANGLE 1 /* Triangular wave (1/2 rect.)*/
#define SND_NOISE 2 /* White noise */
#define SND_PERIODIC 3 /* Periodic noise (not im-ed) */
#define SND_WAVE 4 /* Wave sound set by SetWave()*/
#define SND_MIDI 0x100 /* MIDI instrument (ORable) */
/* Drum() arguments: */
#define DRM_CLICK 0 /* Click (default) */
#define DRM_MIDI 0x100 /* MIDI drum (ORable) */
/* MIDI characteristics: */
#define MIDI_CHANNELS 16 /* Number of MIDI channels */
#define MIDI_MINFREQ 9 /* Min MIDI frequency (Hz) */
#define MIDI_MAXFREQ 12285 /* Max MIDI frequency (Hz) */
#define MIDI_DIVISIONS 1000 /* Number of ticks per second */
/* MIDILogging() arguments: */
#define MIDI_OFF 0 /* Turn MIDI logging off */
#define MIDI_ON 1 /* Turn MIDI logging on */
#define MIDI_TOGGLE 2 /* Toggle MIDI logging */
#define MIDI_QUERY 3 /* Query MIDI logging status */
/** TrashSound() *********************************************/
/** Shut down sound driver. Each driver implements its own **/
/** TrashSound() function. **/
/*************************************************************/
void TrashSound(void);
/** Sound() **************************************************/
/** Generate sound of given frequency (Hz) and volume **/
/** (0..255) via given channel. Setting Freq=0 or Volume=0 **/
/** turns sound off. **/
/*************************************************************/
void Sound(int Channel,int Freq,int Volume);
/** Drum() ***************************************************/
/** Hit a drum of given type with given force (0..255). **/
/** MIDI drums can be used by ORing their numbers with **/
/** SND_MIDI. **/
/*************************************************************/
void Drum(int Type,int Force);
/** SetSound() ***********************************************/
/** Set sound type at a given channel. MIDI instruments can **/
/** be set directly by ORing their numbers with SND_MIDI. **/
/*************************************************************/
void SetSound(int Channel,int NewType);
/** SetChannels() ********************************************/
/** Set master volume (0..255) and switch channels on/off. **/
/** Each channel N has corresponding bit 2^N in Switch. Set **/
/** or reset this bit to turn the channel on or off. **/
/*************************************************************/
void SetChannels(int Volume,int Switch);
/** SetWave() ************************************************/
/** Set waveform for a given channel. The channel will be **/
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
/** waveform to be an instrument or set it to the waveform **/
/** own playback rate. **/
/*************************************************************/
void SetWave(int Channel,const signed char *Data,int Length,int Rate);
/** InitMIDI() ***********************************************/
/** Initialize soundtrack logging into MIDI file FileName. **/
/** Repeated calls to InitMIDI() will close current MIDI **/
/** file and continue logging into a new one. **/
/*************************************************************/
void InitMIDI(const char *FileName);
/** TrashMIDI() **********************************************/
/** Finish logging soundtrack and close the MIDI file. **/
/*************************************************************/
void TrashMIDI(void);
/** MIDILogging() ********************************************/
/** Turn soundtrack logging on/off and return its current **/
/** status. Possible values of Switch are MIDI_OFF (turn **/
/** logging off), MIDI_ON (turn logging on), MIDI_TOGGLE **/
/** (toggle logging), and MIDI_QUERY (just return current **/
/** state of logging). **/
/*************************************************************/
int MIDILogging(int Switch);
/** MIDITicks() **********************************************/
/** Log N 1ms MIDI ticks. **/
/*************************************************************/
void MIDITicks(int N);
#define SND_CHANNELS 16 /* Number of channels */
#define SND_SAMPLESIZE 256 /* Max. SetWave() sample size */
#define SND_BUFSIZE 256 // (22050/50) /* Buffer size, <= 2^SND_BITS */
//#define SND_BITS 8 /* Number of bits in a fragment */
//#define SND_BUFFERS 8 /* Number of fragments, >= 2 */
/* Bigger value results in better behaviour on loaded */
/* but output gets more delayed. */
/** InitSound() **********************************************/
/** Initialize Unix sound driver with given synthesis rate. **/
/** Returns Rate on success, 0 otherwise. Pass Rate=0 to **/
/** skip initialization and be silent. Pass Verbose!=0 to **/
/** see initialization messages. **/
/*************************************************************/
int InitSound(int Rate,int Verbose);
/** StopSound() **********************************************/
/** Temporarily suspend sound. **/
/*************************************************************/
void StopSound(void);
/** ResumeSound() ********************************************/
/** Resume sound after StopSound(). **/
/*************************************************************/
void ResumeSound(void);
/** SndDriver ************************************************/
/** Each sound driver should fill this structure with **/
/** pointers to hardware-dependent handlers. This has to be **/
/** done inside the InitSound() function. **/
/*************************************************************/
struct SndDriverStruct
{
void (*SetSound)(int Channel,int NewType);
void (*Drum)(int Type,int Force);
void (*SetChannels)(int Volume,int Switch);
void (*Sound)(int Channel,int NewFreq,int NewVolume);
void (*SetWave)(int Channel,const signed char *Data,int Length,int Freq);
};
extern struct SndDriverStruct SndDriver;
#endif /* SOUND_H */

Plik diff jest za duży Load Diff

1384
MCUME_pico2/picomsx/Sound.c 100644 → 100755

Plik diff jest za duży Load Diff

89
MCUME_pico2/picomsx/Sound.h 100644 → 100755
Wyświetl plik

@ -6,7 +6,7 @@
/** functions needed to log soundtrack into a MIDI file. **/
/** See Sound.c and the sound drivers for the code. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2003 **/
/** Copyright (C) Marat Fayzullin 1996-2021 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
@ -14,6 +14,14 @@
#ifndef SOUND_H
#define SOUND_H
#ifdef __cplusplus
extern "C" {
#endif
#define sample short
#define BPS16 1
/* SetSound() arguments: */
#define SND_MELODIC 0 /* Melodic sound (default) */
#define SND_RECTANGLE 0 /* Rectangular wave */
@ -39,12 +47,34 @@
#define MIDI_TOGGLE 2 /* Toggle MIDI logging */
#define MIDI_QUERY 3 /* Query MIDI logging status */
/** InitSound() **********************************************/
/** Initialize RenderSound() with given parameters. **/
/*************************************************************/
unsigned int InitSound(unsigned int Rate,unsigned int Latency);
/** TrashSound() *********************************************/
/** Shut down sound driver. Each driver implements its own **/
/** TrashSound() function. **/
/** Shut down RenderSound() driver. **/
/*************************************************************/
void TrashSound(void);
/** RenderAudio() ********************************************/
/** Render given number of melodic sound samples into an **/
/** integer buffer for mixing. **/
/*************************************************************/
void RenderAudio(int *Wave,unsigned int Samples);
/** PlayAudio() **********************************************/
/** Normalize and play given number of samples from the mix **/
/** buffer. Returns the number of samples actually played. **/
/*************************************************************/
unsigned int PlayAudio(int *Wave,unsigned int Samples);
/** RenderAndPlayAudio() *************************************/
/** Render and play a given number of samples. Returns the **/
/** number of samples actually played. **/
/*************************************************************/
unsigned int RenderAndPlayAudio(unsigned int Samples);
/** Sound() **************************************************/
/** Generate sound of given frequency (Hz) and volume **/
/** (0..255) via given channel. Setting Freq=0 or Volume=0 **/
@ -72,6 +102,13 @@ void SetSound(int Channel,int NewType);
/*************************************************************/
void SetChannels(int Volume,int Switch);
/** SetNoise() ***********************************************/
/** Initialize random noise generator to the given Seed and **/
/** then take random output from OUTBit and XOR it with **/
/** XORBit. **/
/*************************************************************/
void SetNoise(int Seed,int OUTBit,int XORBit);
/** SetWave() ************************************************/
/** Set waveform for a given channel. The channel will be **/
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
@ -80,6 +117,18 @@ void SetChannels(int Volume,int Switch);
/*************************************************************/
void SetWave(int Channel,const signed char *Data,int Length,int Rate);
/** GetWave() ************************************************/
/** Get current read position for the buffer set with the **/
/** SetWave() call. Returns 0 if no buffer has been set, or **/
/** if there is no playrate set (i.e. wave is instrument). **/
/*************************************************************/
const signed char *GetWave(int Channel);
/** GetSndRate() *********************************************/
/** Get current sampling rate used for synthesis. **/
/*************************************************************/
unsigned int GetSndRate(void);
/** InitMIDI() ***********************************************/
/** Initialize soundtrack logging into MIDI file FileName. **/
/** Repeated calls to InitMIDI() will close current MIDI **/
@ -106,32 +155,9 @@ int MIDILogging(int Switch);
/*************************************************************/
void MIDITicks(int N);
#define SND_CHANNELS 16 /* Number of channels */
#define SND_SAMPLESIZE 128 //256 /* Max. SetWave() sample size */
#define SND_BUFSIZE 128 //256 /* Buffer size, <= 2^SND_BITS */
#define SND_BITS 8 /* Number of bits in a fragment */
#define SND_BUFFERS 8 /* Number of fragments, >= 2 */
/* Bigger value results in better behaviour on loaded */
/* but output gets more delayed. */
/** InitSound() **********************************************/
/** Initialize Unix sound driver with given synthesis rate. **/
/** Returns Rate on success, 0 otherwise. Pass Rate=0 to **/
/** skip initialization and be silent. Pass Verbose!=0 to **/
/** see initialization messages. **/
/*************************************************************/
int InitSound(int Rate,int Verbose);
/** StopSound() **********************************************/
/** Temporarily suspend sound. **/
/*************************************************************/
void StopSound(void);
/** ResumeSound() ********************************************/
/** Resume sound after StopSound(). **/
/*************************************************************/
void ResumeSound(void);
#if !defined(MSDOS) & !defined(UNIX) & !defined(MAEMO) & !defined(WINDOWS) & !defined(S60) & !defined(UIQ) && !defined(ANDROID)
#define SND_CHANNELS MIDI_CHANNELS /* Default number */
#endif
/** SndDriver ************************************************/
/** Each sound driver should fill this structure with **/
@ -145,8 +171,11 @@ struct SndDriverStruct
void (*SetChannels)(int Volume,int Switch);
void (*Sound)(int Channel,int NewFreq,int NewVolume);
void (*SetWave)(int Channel,const signed char *Data,int Length,int Freq);
const signed char *(*GetWave)(int Channel);
};
extern struct SndDriverStruct SndDriver;
#ifdef __cplusplus
}
#endif
#endif /* SOUND_H */

Wyświetl plik

@ -5,7 +5,8 @@
#define VID_FRAME_SKIP 0x0
#define TFT_VBUFFER_YCROP 0
#define SINGLELINE_RENDERING 1
//#define CUSTOM_SND 1
#define CUSTOM_SND 1
#define CUSTOM_SND_C 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x1
#define FILEBROWSER

Wyświetl plik

@ -334,301 +334,6 @@ void msx_Input(int click) {
static int SoundRate = 0;
static int MasterVolume = 200;
static int MasterSwitch = (1<<SND_CHANNELS)-1;
static int LoopFreq = 25;
static int NoiseGen = 1;
static struct
{
int Type; /* Channel type (SND_*) */
int Freq; /* Channel frequency (Hz) */
int Volume; /* Channel volume (0..255) */
signed char Data[SND_SAMPLESIZE]; /* Wave data (-128..127 each) */
int Length; /* Wave length in Data */
int Rate; /* Wave playback rate (or 0Hz) */
int Pos; /* Wave current position in Data */
int Count; /* Phase counter */
} CH[SND_CHANNELS];
static void handleSoundCmd(unsigned char * Buf, int len)
{
unsigned char R;
int J;
switch(R=Buf[0])
{
case 0xFF: MasterVolume=Buf[1];
MasterSwitch=Buf[2]+Buf[3]*256;
break;
case 0xFE: R=Buf[1];
J=Buf[2]+Buf[3]*256+2;
/* If everything is correct... */
if((R<SND_CHANNELS)&&(J<SND_SAMPLESIZE))
//if(read(PipeFD[0],Buf,2)==2)
//{
J-=2;
CH[R].Type = SND_WAVE;
CH[R].Rate = Buf[0]+Buf[1]*256;
CH[R].Length = J;
CH[R].Count = 0;
CH[R].Pos = 0;
memcpy(CH[R].Data,&Buf[4],J);
J=0;
//I=read(PipeFD[0],CH[R].Data,J);
//if(I>0) J-=I;
//}
break;
case 0xFC: R=Buf[1];
if(R<SND_CHANNELS) CH[R].Type=Buf[2];
break;
default: if(R<SND_CHANNELS)
{
CH[R].Volume = Buf[1];
CH[R].Freq = Buf[2]+Buf[3]*256;
}
break;
}
}
static int Wave[SND_BUFSIZE];
static void mixaudio(char * dest, int size) {
register int J,I,K,L,M,N,L1,L2,A1,A2,V;
/* Waveform generator */
for(J=0,M=MasterSwitch;M&&(J<SND_CHANNELS);J++,M>>=1)
if(CH[J].Freq&&(V=CH[J].Volume)&&(M&1))
switch(CH[J].Type)
{
case SND_NOISE: /* White Noise */
/* For high frequencies, recompute volume */
if(CH[J].Freq<=SoundRate) K=0x10000*CH[J].Freq/SoundRate;
else { V=V*SoundRate/CH[J].Freq;K=0x10000; }
L1=CH[J].Count;
V<<=7;
for(I=0;I<size;I++)
{
L1+=K;
if(L1&0xFFFF0000)
{
L1&=0xFFFF;
if((NoiseGen<<=1)&0x80000000) NoiseGen^=0x08000001;
}
Wave[I]+=NoiseGen&1? V:-V;
}
CH[J].Count=L1;
break;
case SND_WAVE: /* Custom Waveform */
/* Waveform data must have correct length! */
if(CH[J].Length<=0) break;
/* Start counting */
K = CH[J].Rate>0? (SoundRate<<15)/CH[J].Freq/CH[J].Rate
: (SoundRate<<15)/CH[J].Freq/CH[J].Length;
L1 = CH[J].Pos%CH[J].Length;
L2 = CH[J].Count;
A1 = CH[J].Data[L1]*V;
/* If expecting interpolation... */
if(L2<K)
{
/* Compute interpolation parameters */
A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
L = (L2>>15)+1;
N = ((K-(L2&0x7FFF))>>15)+1;
}
/* Add waveform to the buffer */
for(I=0;I<size;I++)
if(L2<K)
{
/* Interpolate linearly */
Wave[I]+=A1+L*(A2-A1)/N;
/* Next waveform step */
L2+=0x8000;
/* Next interpolation step */
L++;
}
else
{
L1 = (L1+L2/K)%CH[J].Length;
L2 = (L2%K)+0x8000;
A1 = CH[J].Data[L1]*V;
Wave[I]+=A1;
/* If expecting interpolation... */
if(L2<K)
{
/* Compute interpolation parameters */
A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
L = 1;
N = ((K-L2)>>15)+1;
}
}
/* End counting */
CH[J].Pos = L1;
CH[J].Count = L2;
break;
case SND_MELODIC: /* Melodic Sound */
case SND_TRIANGLE: /* Triangular Wave */
default: /* Default Sound */
/* Triangular wave has twice less volume */
if(CH[J].Type==SND_TRIANGLE) V=(V+1)>>1;
/* Do not allow frequencies that are too high */
if(CH[J].Freq>=SoundRate/3) break;
K=0x10000*CH[J].Freq/SoundRate;
L1=CH[J].Count;
V<<=7;
for(I=0;I<size;I++)
{
L2=L1+K;
Wave[I]+=L1&0x8000? (L2&0x8000? V:0):(L2&0x8000? 0:-V);
L1=L2;
}
CH[J].Count=L1;
break;
}
#define AUDIO_CONV(A) (128+(A))
/* Mix and convert waveforms */
for(J=0;J<size;J++)
{
I=(Wave[J]*MasterVolume)>>16;
I=I<-128? -128:I>127? 127:I;
//Buf[J]=AUDIO_CONV(I);
*dest++ = I;
*dest++ = I;
Wave[J]=0;
}
}
/** Generate sound of given frequency (Hz) and volume **/
/** (0..255) via given channel. **/
/*************************************************************/
static void DSound(int Channel,int NewFreq,int NewVolume)
{
unsigned char Buf[4];
if((Channel<0)||(Channel>=SND_CHANNELS)) return;
if(!SoundRate||!(MasterSwitch&(1<<Channel))) return;
if(!NewVolume||!NewFreq) { NewVolume=0;NewFreq=0; }
if((CH[Channel].Volume!=NewVolume)||(CH[Channel].Freq!=NewFreq))
{
CH[Channel].Volume = NewVolume;
CH[Channel].Freq = NewFreq;
Buf[0]=Channel;
Buf[1]=NewVolume;
Buf[2]=NewFreq&0xFF;
Buf[3]=NewFreq>>8;
handleSoundCmd(Buf, 4);
// write(PipeFD[1],Buf,4);
}
}
/** Set master volume (0..255) and turn channels on/off. **/
/** Each bit in Toggle corresponds to a channel (1=on). **/
/*************************************************************/
static void DSetChannels(int MVolume,int MSwitch)
{
unsigned char Buf[4];
int J;
if(!SoundRate) return;
/* Sending new MasterVolume/MasterSwitch */
Buf[0]=0xFF;
Buf[1]=MVolume;
Buf[2]=MSwitch&0xFF;
Buf[3]=MSwitch>>8;
handleSoundCmd(Buf, 4);
// write(PipeFD[1],Buf,4);
/* Switching channels on/off */
for(J=0;J<SND_CHANNELS;J++)
if((MSwitch^MasterSwitch)&(1<<J))
{
/* Modifying channel #J */
Buf[0]=J;
/* Set volume/frequency */
if(!(MSwitch&(1<<J))) Buf[1]=Buf[2]=Buf[3]=0;
else
{
Buf[1]=CH[J].Volume;
Buf[2]=CH[J].Freq&0xFF;
Buf[3]=CH[J].Freq>>8;
}
/* Write out */
handleSoundCmd(Buf, 4);
// write(PipeFD[1],Buf,4);
}
/* Set new MasterSwitch value */
MasterSwitch=MSwitch;
MasterVolume=MVolume;
}
/** Set sound type (SND_NOISE/SND_MELODIC) for a given **/
/** channel. **/
/*************************************************************/
static void DSetSound(int Channel,int NewType)
{
unsigned char Buf[4];
if(!SoundRate) return;
if((Channel<0)||(Channel>=SND_CHANNELS)) return;
CH[Channel].Type=NewType;
Buf[0]=0xFC;
Buf[1]=Channel;
Buf[2]=NewType&0xFF;
Buf[3]=NewType>>8;
handleSoundCmd(Buf, 4);
// write(PipeFD[1],Buf,4);
}
/** Set waveform for a given channel. The channel will be **/
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
/** waveform to be an instrument or set it to the waveform **/
/** own playback rate. **/
/*************************************************************/
static void DSetWave(int Channel,const signed char *Data,int Length,int Rate)
{
unsigned char Buf[6+SND_SAMPLESIZE];
if(!SoundRate) return;
if((Channel<0)||(Channel>=SND_CHANNELS)) return;
if((Length<=0)||(Length>SND_SAMPLESIZE)) return;
Buf[0]=0xFE;
Buf[1]=Channel;
Buf[2]=Length&0xFF;
Buf[3]=Length>>8;
Buf[4]=Rate&0xFF;
Buf[5]=Rate>>8;
memcpy(Buf+6,Data,Length);
handleSoundCmd(Buf, 6+Length);
// write(PipeFD[1],Buf,6+Length);
}
static void DDrum(int Type,int Force)
{
}
void msx_Start(char * Cartridge)
{
@ -684,28 +389,10 @@ void msx_Start(char * Cartridge)
word A;
//FILE *F;
#ifdef SOUND_PRESENT
#ifdef HAS_SND
emu_sndInit();
SndDriver.SetSound = DSetSound;
SndDriver.Drum = DDrum;
SndDriver.SetChannels = DSetChannels;
SndDriver.Sound = DSound;
SndDriver.SetWave = DSetWave;
//int J;
/* Reset all channels */
for(J=0;J<SND_CHANNELS;J++)
{
CH[J].Type = SND_MELODIC;
CH[J].Count = 0;
CH[J].Volume = 0;
CH[J].Freq = 0;
}
SoundRate = 22050;
InitSound(22050,0);
#endif
#else
#endif
/* Zero everyting */
#ifdef unused
CasStream=PrnStream=ComIStream=ComOStream=NULL;
@ -1378,17 +1065,25 @@ void msx_Step(void) {
#ifdef HAS_SND
static int wave[256];
#endif
void SND_Process(void *stream, int len) {
//psg_update(stream, 0, len);
mixaudio(stream, len);
#ifdef HAS_SND
audio_sample * snd_buf = (audio_sample *)stream;
memset(wave,0,256*sizeof(wave[0]));
RenderAudio(&wave[0], len);
for (int i = 0; i< len; i++ )
*snd_buf++ = (wave[i]>>8)+128;
#endif
}
void SetColor(byte N,byte R,byte G,byte B)
{
XPal[N] = N;

Wyświetl plik

@ -183,8 +183,10 @@ void * emu_LineBuffer(int line)
#include "AudioPlaySystem.h"
AudioPlaySystem mymixer;
#define AUDIO_BUFFER_LEN (256 ) //(22050/50)
void emu_sndInit() {
tft.begin_audio(256, mymixer.snd_Mixer);
tft.begin_audio(AUDIO_BUFFER_LEN*2, mymixer.snd_Mixer);
mymixer.start();
}

Wyświetl plik

@ -58,6 +58,8 @@ SOFTWARE.
#include "hardware/sync.h"
#endif
#include <string.h>
//#define PSRAM_ASYNC 1
#include "psram_spi.pio.h"
@ -400,6 +402,7 @@ static uint8_t write16_command[] = {
* @param addr Address to write to.
* @param val Value to write.
*/
__force_inline static void psram_write16(psram_spi_inst_t* spi, uint32_t addr, uint16_t val) {
write16_command[3] = addr >> 16;
write16_command[4] = addr >> 8;

Wyświetl plik

@ -10,12 +10,12 @@
#include "psram_spi.h"
#ifdef PSCACHE
Page PSRAM_T::pages[MAX_PAGES];
uint8_t PSRAM_T::nbPages=0;
int8_t PSRAM_T::top=0;
int8_t PSRAM_T::last=0;
#endif
#define RAM_READ 0xB
@ -29,19 +29,22 @@ PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso)
{
}
void PSRAM_T::begin(void)
{
psram_spi = psram_spi_init(pio2, 0);
}
uint8_t PSRAM_T::psram_read(uint32_t addr)
{
return psram_read8(&psram_spi, addr);
}
uint16_t PSRAM_T::psram_read_w(uint32_t addr)
{
return psram_read16(&psram_spi, addr);
}
void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n)
{
@ -55,6 +58,11 @@ void PSRAM_T::psram_write(uint32_t addr, uint8_t val)
psram_write8(&psram_spi, addr, val);
}
void PSRAM_T::psram_write_w(uint32_t addr, uint16_t val)
{
psram_write16(&psram_spi, addr, val);
}
static uint8_t resp[PAGE_SIZE];
@ -71,14 +79,15 @@ void PSRAM_T::psram_write_n(uint32_t addr, uint8_t * val, int n)
void PSRAM_T::pswrite(uint32_t addr, uint8_t val)
{
psram_write(addr, val);
//return;
#ifdef PSCACHE
uint32_t curPage=addr&(~(PAGE_SIZE-1));
for (int i=0; i<nbPages; i++) {
if (pages[i].pageid == curPage) {
pages[i].page[addr&(PAGE_SIZE-1)] = val;
break;
}
}
}
#endif
}
@ -86,8 +95,7 @@ void PSRAM_T::pswrite(uint32_t addr, uint8_t val)
uint8_t PSRAM_T::psread(uint32_t addr)
{
//uint8_t val = psram_read(addr);
//return val;
#ifdef PSCACHE
uint32_t curPage=addr&(~(PAGE_SIZE-1));
uint32_t offs = addr&(PAGE_SIZE-1);
@ -136,10 +144,14 @@ uint8_t PSRAM_T::psread(uint32_t addr)
//emu_printi(curPage);
psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);
return pages[top].page[offs];
#else
return psram_read(addr);
#endif
}
uint16_t PSRAM_T::psread_w(uint32_t addr)
{
#ifdef PSCACHE
uint32_t curPage=addr&(~(PAGE_SIZE-1));
uint32_t offs = addr&(PAGE_SIZE-1);
@ -188,5 +200,23 @@ uint16_t PSRAM_T::psread_w(uint32_t addr)
//emu_printi(curPage);
psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);
return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
#else
return psram_read_w(addr);
#endif
}
void PSRAM_T::pswrite_w(uint32_t addr, uint16_t val)
{
psram_write_w(addr, val);
#ifdef PSCACHE
uint32_t curPage=addr&(~(PAGE_SIZE-1));
for (int i=0; i<nbPages; i++) {
if (pages[i].pageid == curPage) {
pages[i].page[addr&(PAGE_SIZE-1)] = val&0xff;
pages[i].page[(addr+1)&(PAGE_SIZE-1)] = val>>8 ;
break;
}
}
#endif
}

Wyświetl plik

@ -10,6 +10,10 @@
#include "pico.h"
#include "pico/stdlib.h"
#define PSCACHE 1
//#define PAGE_SIZE 16 //32 //2048 //1024
//#define MAX_PAGES 8
#define PAGE_SIZE 16 //32 //2048 //1024
#define MAX_PAGES 8
@ -30,11 +34,14 @@ class PSRAM_T
void pswrite(uint32_t addr, uint8_t val);
uint8_t psread(uint32_t addr);
uint16_t psread_w(uint32_t addr);
void pswrite_w(uint32_t addr, uint16_t val);
private:
static uint8_t psram_read(uint32_t addr);
static uint16_t psram_read_w(uint32_t addr);
static void psram_read_n(uint32_t addr, uint8_t * val, int n);
static void psram_write(uint32_t addr, uint8_t val);
static void psram_write_w(uint32_t addr, uint16_t val);
static void psram_write_n(uint32_t addr, uint8_t * val, int n);
protected:

Wyświetl plik

@ -111,10 +111,10 @@ static int conv_table_uk[128][2] =
{KBD_KEY_F6 , KBD_KEY_F6}, /* 0x3f */ \
{KBD_KEY_F7 , KBD_KEY_F7}, /* 0x40 */ \
{KBD_KEY_F8 , KBD_KEY_F8}, /* 0x41 */ \
{0 , 0 }, /* 0x42 */ \
{0 , 0 }, /* 0x43 */ \
{0 , 0 }, /* 0x44 */ \
{0 , 0 }, /* 0x45 */ \
{KBD_KEY_F9 , KBD_KEY_F9}, /* 0x42 */ \
{KBD_KEY_F10 , KBD_KEY_F10}, /* 0x43 */ \
{KBD_KEY_F11 , KBD_KEY_F11}, /* 0x44 */ \
{KBD_KEY_F12 , KBD_KEY_F12}, /* 0x45 */ \
{0 , 0 }, /* 0x46 */ \
{0 , 0 }, /* 0x47 */ \
{0 , 0 }, /* 0x48 */ \
@ -222,10 +222,10 @@ static int conv_table_be[128][2] =
{KBD_KEY_F6 , KBD_KEY_F6}, /* 0x3f */ \
{KBD_KEY_F7 , KBD_KEY_F7}, /* 0x40 */ \
{KBD_KEY_F8 , KBD_KEY_F8}, /* 0x41 */ \
{0 , 0 }, /* 0x42 */ \
{0 , 0 }, /* 0x43 */ \
{0 , 0 }, /* 0x44 */ \
{0 , 0 }, /* 0x45 */ \
{KBD_KEY_F9 , KBD_KEY_F9}, /* 0x42 */ \
{KBD_KEY_F10 , KBD_KEY_F10}, /* 0x43 */ \
{KBD_KEY_F11 , KBD_KEY_F11}, /* 0x44 */ \
{KBD_KEY_F12 , KBD_KEY_F12}, /* 0x45 */ \
{0 , 0 }, /* 0x46 */ \
{0 , 0 }, /* 0x47 */ \
{0 , 0 }, /* 0x48 */ \

Wyświetl plik

@ -26,7 +26,10 @@
#define KBD_KEY_F6 1016
#define KBD_KEY_F7 1017
#define KBD_KEY_F8 1018
#define KBD_KEY_F9 1019
#define KBD_KEY_F10 1020
#define KBD_KEY_F11 1021
#define KBD_KEY_F12 1022
#define KEY_PRESSED 1
#define KEY_RELEASED 0