kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
add AtariST emulation
rodzic
99ff03ea62
commit
fdc2f72477
|
@ -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.
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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
Plik diff jest za duży
Load Diff
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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 *)®[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
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
Plik diff jest za duży
Load Diff
|
@ -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
|
||||
};
|
|
@ -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
|
||||
};
|
|
@ -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
|
@ -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
|
|
@ -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
Plik diff jest za duży
Load Diff
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */ \
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue