mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-06-08 09:29:31 +00:00
Remove BeOS and AmigaOS
This commit is contained in:
parent
58e367a73d
commit
06747d4a7b
|
@ -39,8 +39,7 @@ Some features of Basilisk II:
|
|||
- Serial drivers
|
||||
- SCSI Manager (old-style) emulation
|
||||
- Emulates extended ADB keyboard and 3-button mouse
|
||||
- Uses UAE 68k emulation or (under AmigaOS and NetBSD/m68k) real 68k
|
||||
processor
|
||||
- Uses UAE 68k emulation or real 68k processor
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
|
|
@ -6,9 +6,6 @@ RELEASE := $(shell sed <BasiliskII.spec -n '/^\%define release */s///p')
|
|||
VERNAME := BasiliskII-$(VERSION)
|
||||
|
||||
SRCARCHIVE := $(shell date +BasiliskII_src_%d%m%Y.tar.gz)
|
||||
AMIGAARCHIVE := $(VERNAME)-$(RELEASE).amiga.lzh
|
||||
BEOSPPCARCHIVE := $(VERNAME)-$(RELEASE).beosppc.zip
|
||||
BEOSX86ARCHIVE := $(VERNAME)-$(RELEASE).beosx86.zip
|
||||
MACOSXARCHIVE := $(VERNAME)-$(RELEASE).tar.gz
|
||||
|
||||
TMPDIR := $(shell date +/tmp/build%M%S)
|
||||
|
@ -27,14 +24,10 @@ help:
|
|||
@echo "The following targets are available:"
|
||||
@echo " tarball source tarball ($(SRCARCHIVE))"
|
||||
@echo " rpm source and binary RPMs"
|
||||
@echo " amiga AmigaOS binary archive ($(AMIGAARCHIVE))"
|
||||
@echo " beosppc BeOS/ppc binary archive ($(BEOSPPCARCHIVE))"
|
||||
@echo " beosx86 BeOS/x86 binary archive ($(BEOSX86ARCHIVE))"
|
||||
@echo " macosx MacOS X binary archive ($(MACOSXARCHIVE))"
|
||||
|
||||
clean:
|
||||
-rm -f $(SRCARCHIVE)
|
||||
-rm -f $(AMIGAARCHIVE) $(BEOSPPCARCHIVE) $(BEOSX86ARCHIVE)
|
||||
|
||||
#
|
||||
# Source tarball
|
||||
|
@ -59,55 +52,6 @@ $(SRCARCHIVE): $(SRCS) $(DOCS)
|
|||
rpm: $(SRCARCHIVE)
|
||||
rpmbuild -ta --clean $(SRCARCHIVE)
|
||||
|
||||
#
|
||||
# Binary archive for AmigaOS
|
||||
#
|
||||
amiga: $(AMIGAARCHIVE)
|
||||
|
||||
$(AMIGAARCHIVE): $(SRCS) $(DOCS) src/AmigaOS/BasiliskII
|
||||
-rm -rf $(TMPDIR)
|
||||
mkdir $(TMPDIR)
|
||||
mkdir $(TMPDIR)/$(VERNAME)
|
||||
cp $(DOCS) $(TMPDIR)/$(VERNAME)
|
||||
cp src/AmigaOS/BasiliskII $(TMPDIR)/$(VERNAME)
|
||||
cp src/AmigaOS/BasiliskII.info $(TMPDIR)/$(VERNAME)
|
||||
chmod 775 $(TMPDIR)/$(VERNAME)/BasiliskII
|
||||
cd $(TMPDIR); lha a $@ $(VERNAME)
|
||||
mv $(TMPDIR)/$@ .
|
||||
rm -rf $(TMPDIR)
|
||||
|
||||
#
|
||||
# Binary archive for BeOS/ppc
|
||||
#
|
||||
beosppc: $(BEOSPPCARCHIVE)
|
||||
|
||||
$(BEOSPPCARCHIVE): $(SRCS) $(DOCS) src/BeOS/obj.ppc/BasiliskII
|
||||
-rm -rf $(TMPDIR)
|
||||
mkdir $(TMPDIR)
|
||||
mkdir $(TMPDIR)/$(VERNAME)
|
||||
cp $(DOCS) $(TMPDIR)/$(VERNAME)
|
||||
cp src/BeOS/obj.ppc/BasiliskII $(TMPDIR)/$(VERNAME)
|
||||
mimeset -f $(TMPDIR)
|
||||
cd $(TMPDIR); zip -ry $@ $(VERNAME)/
|
||||
mv $(TMPDIR)/$@ .
|
||||
rm -rf $(TMPDIR)
|
||||
|
||||
#
|
||||
# Binary archive for BeOS/x86
|
||||
#
|
||||
beosx86: $(BEOSX86ARCHIVE)
|
||||
|
||||
$(BEOSX86ARCHIVE): $(SRCS) $(DOCS) src/BeOS/obj.x86/BasiliskII
|
||||
-rm -rf $(TMPDIR)
|
||||
mkdir $(TMPDIR)
|
||||
mkdir $(TMPDIR)/$(VERNAME)
|
||||
cp $(DOCS) $(TMPDIR)/$(VERNAME)
|
||||
cp src/BeOS/obj.x86/BasiliskII $(TMPDIR)/$(VERNAME)
|
||||
mimeset -f $(TMPDIR)
|
||||
cd $(TMPDIR); zip -ry $@ $(VERNAME)/
|
||||
mv $(TMPDIR)/$@ .
|
||||
rm -rf $(TMPDIR)
|
||||
|
||||
#
|
||||
# Binary archive for MacOS X
|
||||
#
|
||||
|
|
Binary file not shown.
|
@ -1,64 +0,0 @@
|
|||
# AmigaOS makefile for Basilisk II (GeekGadgets tool chain)
|
||||
|
||||
## System specific configuration
|
||||
CC = gcc
|
||||
CXX = c++
|
||||
CXXFLAGS = -g -O1 -noixemul -m68020 -msmall-code -Wno-multichar
|
||||
CPPFLAGS = -I../include -I../native_cpu -I.
|
||||
DEFS =
|
||||
LDFLAGS = -noixemul
|
||||
LIBS = /gg/lib/libnix/swapstack.o
|
||||
AS = PhxAss
|
||||
ASFLAGS = OPT ! INCPATH GG:os-include FPU=1
|
||||
|
||||
## Files
|
||||
SRCS = ../main.cpp main_amiga.cpp ../prefs.cpp ../prefs_items.cpp \
|
||||
prefs_amiga.cpp prefs_editor_amiga.cpp sys_amiga.cpp ../rom_patches.cpp \
|
||||
../slot_rom.cpp ../rsrc_patches.cpp ../emul_op.cpp \
|
||||
../macos_util.cpp ../xpram.cpp xpram_amiga.cpp ../timer.cpp \
|
||||
timer_amiga.cpp clip_amiga.cpp ../adb.cpp ../serial.cpp \
|
||||
serial_amiga.cpp ../ether.cpp ether_amiga.cpp ../sony.cpp ../disk.cpp \
|
||||
../cdrom.cpp ../scsi.cpp scsi_amiga.cpp ../video.cpp video_amiga.cpp \
|
||||
../audio.cpp audio_amiga.cpp ../extfs.cpp extfs_amiga.cpp \
|
||||
../user_strings.cpp user_strings_amiga.cpp asm_support.asm
|
||||
APP = BasiliskII
|
||||
|
||||
## Rules
|
||||
.PHONY: clean distclean
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .cpp .asm .o .h
|
||||
|
||||
all: $(APP)
|
||||
|
||||
OBJ_DIR = obj
|
||||
$(OBJ_DIR)::
|
||||
@[ -d $(OBJ_DIR) ] || mkdir $(OBJ_DIR) > /dev/null 2>&1
|
||||
|
||||
define SRCS_LIST_TO_OBJS
|
||||
$(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(foreach file, $(SRCS), \
|
||||
$(basename $(notdir $(file))))))
|
||||
endef
|
||||
OBJS = $(SRCS_LIST_TO_OBJS)
|
||||
|
||||
SRC_PATHS += $(sort $(foreach file, $(SRCS), $(dir $(file))))
|
||||
VPATH :=
|
||||
VPATH += $(addprefix :, $(subst ,:, $(filter-out $($(subst, :, ,$(VPATH))), $(SRC_PATHS))))
|
||||
|
||||
$(APP): $(OBJ_DIR) $(OBJS)
|
||||
$(CXX) -o $(APP) $(LDFLAGS) $(LIBS) $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(APP) $(OBJ_DIR)/* *~ *.bak obj.0000.*
|
||||
|
||||
distclean: clean
|
||||
rm -rf $(OBJ_DIR)
|
||||
|
||||
$(OBJ_DIR)/%.o : %.cpp
|
||||
$(CXX) $(CPPFLAGS) $(DEFS) $(CXXFLAGS) -c $< -o $@
|
||||
$(OBJ_DIR)/%.o : %.asm
|
||||
$(AS) $(ASFLAGS) $< TO $(OBJ_DIR)/$*.obj
|
||||
hunk2aout $(OBJ_DIR)/$*.obj >/dev/null
|
||||
mv obj.0000.* $@
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
File diff suppressed because it is too large
Load Diff
|
@ -1,515 +0,0 @@
|
|||
/*
|
||||
* audio_amiga.cpp - Audio support, AmigaOS implementation using AHI
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <devices/ahi.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/exec.h>
|
||||
#include <proto/ahi.h>
|
||||
#include <inline/exec.h>
|
||||
#include <inline/ahi.h>
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "audio.h"
|
||||
#include "audio_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define D1(x) ;
|
||||
|
||||
|
||||
// Global variables
|
||||
static ULONG ahi_id = AHI_DEFAULT_ID; // AHI audio ID
|
||||
static struct AHIAudioCtrl *ahi_ctrl = NULL;
|
||||
static struct AHISampleInfo sample[2]; // Two sample infos for double-buffering
|
||||
static struct Hook sf_hook;
|
||||
static int play_buf = 0; // Number of currently played buffer
|
||||
static long sound_buffer_size; // Size of one audio buffer in bytes
|
||||
static int audio_block_fetched = 0; // Number of audio blocks fetched by interrupt routine
|
||||
|
||||
static bool main_mute = false;
|
||||
static bool speaker_mute = false;
|
||||
static ULONG supports_volume_changes = false;
|
||||
static ULONG supports_stereo_panning = false;
|
||||
static ULONG current_main_volume;
|
||||
static ULONG current_speaker_volume;
|
||||
|
||||
|
||||
// Prototypes
|
||||
static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/);
|
||||
void audio_set_sample_rate_byval(uint32 value);
|
||||
void audio_set_sample_size_byval(uint32 value);
|
||||
void audio_set_channels_byval(uint32 value);
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(int sample_rate_index)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[sample_rate_index];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
sample[0].ahisi_Address = sample[1].ahisi_Address = NULL;
|
||||
|
||||
// Init audio status and feature flags
|
||||
audio_channel_counts.push_back(2);
|
||||
// set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
||||
// Sound disabled in prefs? Then do nothing
|
||||
if (PrefsFindBool("nosound"))
|
||||
return;
|
||||
|
||||
// AHI available?
|
||||
if (AHIBase == NULL) {
|
||||
WarningAlert(GetString(STR_NO_AHI_WARN));
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize callback hook
|
||||
sf_hook.h_Entry = (HOOKFUNC)audio_callback;
|
||||
|
||||
// Read "sound" preferences
|
||||
const char *str = PrefsFindString("sound");
|
||||
if (str)
|
||||
sscanf(str, "ahi/%08lx", &ahi_id);
|
||||
|
||||
// Open audio control structure
|
||||
if ((ahi_ctrl = AHI_AllocAudio(
|
||||
AHIA_AudioID, ahi_id,
|
||||
AHIA_MixFreq, AudioStatus.sample_rate >> 16,
|
||||
AHIA_Channels, 1,
|
||||
AHIA_Sounds, 2,
|
||||
AHIA_SoundFunc, (ULONG)&sf_hook,
|
||||
TAG_END)) == NULL) {
|
||||
WarningAlert(GetString(STR_NO_AHI_CTRL_WARN));
|
||||
return;
|
||||
}
|
||||
|
||||
ULONG max_channels, sample_rate, frequencies, sample_rate_index;
|
||||
|
||||
AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
|
||||
AHIDB_MaxChannels, (ULONG) &max_channels,
|
||||
AHIDB_Frequencies, (ULONG) &frequencies,
|
||||
TAG_END);
|
||||
|
||||
D(bug("AudioInit: max_channels=%ld frequencies=%ld\n", max_channels, frequencies));
|
||||
|
||||
for (int n=0; n<frequencies; n++)
|
||||
{
|
||||
AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
|
||||
AHIDB_FrequencyArg, n,
|
||||
AHIDB_Frequency, (ULONG) &sample_rate,
|
||||
TAG_END);
|
||||
|
||||
D(bug("AudioInit: f=%ld Hz\n", sample_rate));
|
||||
audio_sample_rates.push_back(sample_rate << 16);
|
||||
}
|
||||
|
||||
ULONG sample_size_bits = 16;
|
||||
|
||||
D(bug("AudioInit: sampe_rates=%ld\n", audio_sample_rates.size() ));
|
||||
|
||||
// get index of sample rate closest to 22050 Hz
|
||||
AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
|
||||
AHIDB_IndexArg, 22050,
|
||||
AHIDB_Bits, (ULONG) &sample_size_bits,
|
||||
AHIDB_Index, (ULONG) &sample_rate_index,
|
||||
AHIDB_Volume, (ULONG) &supports_volume_changes,
|
||||
AHIDB_Panning, (ULONG) &supports_stereo_panning,
|
||||
TAG_END);
|
||||
|
||||
audio_sample_sizes.push_back(16);
|
||||
|
||||
set_audio_status_format(sample_rate_index);
|
||||
|
||||
// 2048 frames per block
|
||||
audio_frames_per_block = 2048;
|
||||
sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
|
||||
|
||||
// Prepare SampleInfos and load sounds (two sounds for double buffering)
|
||||
sample[0].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S;
|
||||
sample[0].ahisi_Length = audio_frames_per_block;
|
||||
sample[0].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR);
|
||||
sample[1].ahisi_Type = AudioStatus.sample_size == 16 ? AHIST_S16S : AHIST_S8S;
|
||||
sample[1].ahisi_Length = audio_frames_per_block;
|
||||
sample[1].ahisi_Address = AllocVec(sound_buffer_size, MEMF_PUBLIC | MEMF_CLEAR);
|
||||
if (sample[0].ahisi_Address == NULL || sample[1].ahisi_Address == NULL)
|
||||
return;
|
||||
|
||||
AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample[0], ahi_ctrl);
|
||||
AHI_LoadSound(1, AHIST_DYNAMICSAMPLE, &sample[1], ahi_ctrl);
|
||||
|
||||
// Set parameters
|
||||
play_buf = 0;
|
||||
current_main_volume = current_speaker_volume = 0x10000;
|
||||
AHI_SetVol(0, current_speaker_volume, 0x8000, ahi_ctrl, AHISF_IMM);
|
||||
|
||||
AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, AHISF_IMM);
|
||||
AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, AHISF_IMM);
|
||||
|
||||
// Everything OK
|
||||
audio_open = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void AudioExit(void)
|
||||
{
|
||||
// Free everything
|
||||
if (ahi_ctrl != NULL) {
|
||||
AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END);
|
||||
AHI_FreeAudio(ahi_ctrl);
|
||||
}
|
||||
|
||||
FreeVec(sample[0].ahisi_Address);
|
||||
FreeVec(sample[1].ahisi_Address);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* First source added, start audio stream
|
||||
*/
|
||||
|
||||
void audio_enter_stream()
|
||||
{
|
||||
AHI_ControlAudio(ahi_ctrl, AHIC_Play, TRUE, TAG_END);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Last source removed, stop audio stream
|
||||
*/
|
||||
|
||||
void audio_exit_stream()
|
||||
{
|
||||
AHI_ControlAudio(ahi_ctrl, AHIC_Play, FALSE, TAG_END);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AHI sound callback, request next buffer
|
||||
*/
|
||||
|
||||
static __saveds __attribute__((regparm(3))) ULONG audio_callback(struct Hook *hook /*a0*/, struct AHISoundMessage *msg /*a1*/, struct AHIAudioCtrl *ahi_ctrl /*a2*/)
|
||||
{
|
||||
play_buf ^= 1;
|
||||
|
||||
// New buffer available?
|
||||
if (audio_block_fetched)
|
||||
{
|
||||
audio_block_fetched--;
|
||||
|
||||
if (main_mute || speaker_mute)
|
||||
{
|
||||
memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get size of audio data
|
||||
uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
|
||||
if (apple_stream_info) {
|
||||
int32 sample_count = ReadMacInt32(apple_stream_info + scd_sampleCount);
|
||||
|
||||
uint32 num_channels = ReadMacInt16(apple_stream_info + scd_numChannels);
|
||||
uint32 sample_size = ReadMacInt16(apple_stream_info + scd_sampleSize);
|
||||
uint32 sample_rate = ReadMacInt32(apple_stream_info + scd_sampleRate);
|
||||
|
||||
D(bug("stream: sample_count=%ld num_channels=%ld sample_size=%ld sample_rate=%ld\n", sample_count, num_channels, sample_size, sample_rate >> 16));
|
||||
|
||||
// Yes, this can happen.
|
||||
if(sample_count != 0) {
|
||||
if(sample_rate != AudioStatus.sample_rate) {
|
||||
audio_set_sample_rate_byval(sample_rate);
|
||||
}
|
||||
if(num_channels != AudioStatus.channels) {
|
||||
audio_set_channels_byval(num_channels);
|
||||
}
|
||||
if(sample_size != AudioStatus.sample_size) {
|
||||
audio_set_sample_size_byval(sample_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (sample_count < 0)
|
||||
sample_count = 0;
|
||||
|
||||
int work_size = sample_count * num_channels * (sample_size>>3);
|
||||
D(bug("stream: work_size=%ld sound_buffer_size=%ld\n", work_size, sound_buffer_size));
|
||||
|
||||
if (work_size > sound_buffer_size)
|
||||
work_size = sound_buffer_size;
|
||||
|
||||
// Put data into AHI buffer (convert 8-bit data unsigned->signed)
|
||||
if (AudioStatus.sample_size == 16)
|
||||
Mac2Host_memcpy(sample[play_buf].ahisi_Address, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
|
||||
else {
|
||||
uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
|
||||
uint32 *q = (uint32 *)sample[play_buf].ahisi_Address;
|
||||
int r = work_size >> 2;
|
||||
while (r--)
|
||||
*q++ = *p++ ^ 0x80808080;
|
||||
}
|
||||
if (work_size != sound_buffer_size)
|
||||
memset((uint8 *)sample[play_buf].ahisi_Address + work_size, 0, sound_buffer_size - work_size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
memset(sample[play_buf].ahisi_Address, 0, sound_buffer_size);
|
||||
|
||||
// Play next buffer
|
||||
AHI_SetSound(0, play_buf, 0, 0, ahi_ctrl, 0);
|
||||
|
||||
// Trigger audio interrupt to get new buffer
|
||||
if (AudioStatus.num_sources) {
|
||||
D1(bug("stream: triggering irq\n"));
|
||||
SetInterruptFlag(INTFLAG_AUDIO);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MacOS audio interrupt, read next data block
|
||||
*/
|
||||
|
||||
void AudioInterrupt(void)
|
||||
{
|
||||
D1(bug("AudioInterrupt\n"));
|
||||
|
||||
// Get data from apple mixer
|
||||
if (AudioStatus.mixer) {
|
||||
M68kRegisters r;
|
||||
r.a[0] = audio_data + adatStreamInfo;
|
||||
r.a[1] = AudioStatus.mixer;
|
||||
Execute68k(audio_data + adatGetSourceData, &r);
|
||||
D1(bug(" GetSourceData() returns %08lx\n", r.d[0]));
|
||||
} else
|
||||
WriteMacInt32(audio_data + adatStreamInfo, 0);
|
||||
|
||||
// Signal stream function
|
||||
audio_block_fetched++;
|
||||
D1(bug("AudioInterrupt done\n"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set sampling parameters
|
||||
* "index" is an index into the audio_sample_rates[] etc. arrays
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
void audio_set_sample_rate_byval(uint32 value)
|
||||
{
|
||||
bool changed = (AudioStatus.sample_rate != value);
|
||||
if(changed)
|
||||
{
|
||||
ULONG sample_rate_index;
|
||||
|
||||
// get index of sample rate closest to <value> Hz
|
||||
AHI_GetAudioAttrs(ahi_id, ahi_ctrl,
|
||||
AHIDB_IndexArg, value >> 16,
|
||||
AHIDB_Index, (ULONG) &sample_rate_index,
|
||||
TAG_END);
|
||||
|
||||
D(bug(" audio_set_sample_rate_byval requested rate=%ld Hz\n", value >> 16));
|
||||
|
||||
AudioStatus.sample_rate = audio_sample_rates[sample_rate_index];
|
||||
|
||||
AHI_SetFreq(0, AudioStatus.sample_rate >> 16, ahi_ctrl, 0);
|
||||
}
|
||||
|
||||
D(bug(" audio_set_sample_rate_byval rate=%ld Hz\n", AudioStatus.sample_rate >> 16));
|
||||
}
|
||||
|
||||
void audio_set_sample_size_byval(uint32 value)
|
||||
{
|
||||
bool changed = (AudioStatus.sample_size != value);
|
||||
if(changed) {
|
||||
// AudioStatus.sample_size = value;
|
||||
// update_sound_parameters();
|
||||
// WritePrivateProfileInt( "Audio", "SampleSize", AudioStatus.sample_size, ini_file_name );
|
||||
}
|
||||
D(bug(" audio_set_sample_size_byval %d\n", AudioStatus.sample_size));
|
||||
}
|
||||
|
||||
void audio_set_channels_byval(uint32 value)
|
||||
{
|
||||
bool changed = (AudioStatus.channels != value);
|
||||
if(changed) {
|
||||
// AudioStatus.channels = value;
|
||||
// update_sound_parameters();
|
||||
// WritePrivateProfileInt( "Audio", "Channels", AudioStatus.channels, ini_file_name );
|
||||
}
|
||||
D(bug(" audio_set_channels_byval %d\n", AudioStatus.channels));
|
||||
}
|
||||
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
if(index >= 0 && index < audio_sample_rates.size() ) {
|
||||
audio_set_sample_rate_byval( audio_sample_rates[index] );
|
||||
D(bug(" audio_set_sample_rate index=%ld rate=%ld\n", index, AudioStatus.sample_rate >> 16));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
if(index >= 0 && index < audio_sample_sizes.size() ) {
|
||||
audio_set_sample_size_byval( audio_sample_sizes[index] );
|
||||
D(bug(" audio_set_sample_size %d,%d\n", index,AudioStatus.sample_size));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
if(index >= 0 && index < audio_channel_counts.size() ) {
|
||||
audio_set_channels_byval( audio_channel_counts[index] );
|
||||
D(bug(" audio_set_channels %d,%d\n", index,AudioStatus.channels));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get/set volume controls (volume values received/returned have the left channel
|
||||
* volume in the upper 16 bits and the right channel volume in the lower 16 bits;
|
||||
* both volumes are 8.8 fixed point values with 0x0100 meaning "maximum volume"))
|
||||
*/
|
||||
|
||||
bool audio_get_main_mute(void)
|
||||
{
|
||||
D(bug("audio_get_main_mute: mute=%ld\n", main_mute));
|
||||
|
||||
return main_mute;
|
||||
}
|
||||
|
||||
uint32 audio_get_main_volume(void)
|
||||
{
|
||||
D(bug("audio_get_main_volume\n"));
|
||||
|
||||
ULONG volume = current_main_volume >> 8; // 0x10000 => 0x100
|
||||
|
||||
D(bug("audio_get_main_volume: volume=%08lx\n", volume));
|
||||
|
||||
return (volume << 16) + volume;
|
||||
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
bool audio_get_speaker_mute(void)
|
||||
{
|
||||
D(bug("audio_get_speaker_mute: mute=%ld\n", speaker_mute));
|
||||
|
||||
return speaker_mute;
|
||||
}
|
||||
|
||||
uint32 audio_get_speaker_volume(void)
|
||||
{
|
||||
D(bug("audio_get_speaker_volume: \n"));
|
||||
|
||||
if (audio_open)
|
||||
{
|
||||
ULONG volume = current_speaker_volume >> 8; // 0x10000 => 0x100
|
||||
|
||||
D(bug("audio_get_speaker_volume: volume=%08lx\n", volume));
|
||||
|
||||
return (volume << 16) + volume;
|
||||
}
|
||||
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
void audio_set_main_mute(bool mute)
|
||||
{
|
||||
D(bug("audio_set_main_mute: mute=%ld\n", mute));
|
||||
|
||||
if (mute != main_mute)
|
||||
{
|
||||
main_mute = mute;
|
||||
}
|
||||
}
|
||||
|
||||
void audio_set_main_volume(uint32 vol)
|
||||
{
|
||||
D(bug("audio_set_main_volume: vol=%08lx\n", vol));
|
||||
|
||||
if (audio_open && supports_volume_changes)
|
||||
{
|
||||
ULONG volume = 0x80 * ((vol >> 16) + (vol & 0xffff));
|
||||
|
||||
D(bug("audio_set_main_volume: volume=%08lx\n", volume));
|
||||
|
||||
current_main_volume = volume;
|
||||
|
||||
AHI_SetVol(0, volume, 0x8000, ahi_ctrl, AHISF_IMM);
|
||||
}
|
||||
}
|
||||
|
||||
void audio_set_speaker_mute(bool mute)
|
||||
{
|
||||
D(bug("audio_set_speaker_mute: mute=%ld\n", mute));
|
||||
|
||||
if (mute != speaker_mute)
|
||||
{
|
||||
speaker_mute = mute;
|
||||
}
|
||||
}
|
||||
|
||||
void audio_set_speaker_volume(uint32 vol)
|
||||
{
|
||||
D(bug("audio_set_speaker_volume: vol=%08lx\n", vol));
|
||||
|
||||
if (audio_open && supports_volume_changes)
|
||||
{
|
||||
ULONG volume = 0x80 * ((vol >> 16) + (vol & 0xffff));
|
||||
|
||||
D(bug("audio_set_speaker_volume: volume=%08lx\n", volume));
|
||||
|
||||
current_speaker_volume = volume;
|
||||
|
||||
AHI_SetVol(0, volume, 0x8000, ahi_ctrl, AHISF_IMM);
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* clip_amiga.cpp - Clipboard handling, AmigaOS implementation
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <libraries/iffparse.h>
|
||||
#include <devices/clipboard.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/exec.h>
|
||||
#include <proto/iffparse.h>
|
||||
#include <inline/exec.h>
|
||||
#include <inline/iffparse.h>
|
||||
|
||||
#include "clip.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Global variables
|
||||
static struct IFFHandle *iffw = NULL;
|
||||
static struct ClipboardHandle *ch = NULL;
|
||||
static bool clipboard_open = false;
|
||||
static bool no_clip_conversion;
|
||||
|
||||
|
||||
// Conversion tables
|
||||
static const uint8 mac2iso[0x80] = {
|
||||
0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
|
||||
0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
|
||||
0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
|
||||
0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
|
||||
0x2b, 0xb0, 0xa2, 0xa3, 0xa7, 0xb7, 0xb6, 0xdf,
|
||||
0xae, 0xa9, 0x20, 0xb4, 0xa8, 0x23, 0xc6, 0xd8,
|
||||
0x20, 0xb1, 0x3c, 0x3e, 0xa5, 0xb5, 0xf0, 0x53,
|
||||
0x50, 0x70, 0x2f, 0xaa, 0xba, 0x4f, 0xe6, 0xf8,
|
||||
0xbf, 0xa1, 0xac, 0x2f, 0x66, 0x7e, 0x44, 0xab,
|
||||
0xbb, 0x2e, 0x20, 0xc0, 0xc3, 0xd5, 0x4f, 0x6f,
|
||||
0x2d, 0x2d, 0x22, 0x22, 0x60, 0x27, 0xf7, 0x20,
|
||||
0xff, 0x59, 0x2f, 0xa4, 0x3c, 0x3e, 0x66, 0x66,
|
||||
0x23, 0xb7, 0x2c, 0x22, 0x25, 0xc2, 0xca, 0xc1,
|
||||
0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
|
||||
0x20, 0xd2, 0xda, 0xdb, 0xd9, 0x69, 0x5e, 0x7e,
|
||||
0xaf, 0x20, 0xb7, 0xb0, 0xb8, 0x22, 0xb8, 0x20
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void ClipInit(void)
|
||||
{
|
||||
no_clip_conversion = PrefsFindBool("noclipconversion");
|
||||
|
||||
// Create clipboard IFF handle
|
||||
iffw = AllocIFF();
|
||||
if (iffw) {
|
||||
ch = OpenClipboard(PRIMARY_CLIP);
|
||||
if (ch) {
|
||||
iffw->iff_Stream = (ULONG)ch;
|
||||
InitIFFasClip(iffw);
|
||||
clipboard_open = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void ClipExit(void)
|
||||
{
|
||||
if (ch)
|
||||
CloseClipboard(ch);
|
||||
if (iffw)
|
||||
FreeIFF(iffw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac application zeroes clipboard
|
||||
*/
|
||||
|
||||
void ZeroScrap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac application reads clipboard
|
||||
*/
|
||||
|
||||
void GetScrap(void **handle, uint32 type, int32 offset)
|
||||
{
|
||||
D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mac application wrote to clipboard
|
||||
*/
|
||||
|
||||
void PutScrap(uint32 type, void *scrap, int32 length)
|
||||
{
|
||||
D(bug("PutScrap type %08lx, data %08lx, length %ld\n", type, scrap, length));
|
||||
if (length <= 0 || !clipboard_open)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case 'TEXT': {
|
||||
D(bug(" clipping TEXT\n"));
|
||||
|
||||
// Open IFF stream
|
||||
if (OpenIFF(iffw, IFFF_WRITE))
|
||||
break;
|
||||
|
||||
// Convert text from Mac charset to ISO-Latin1
|
||||
uint8 *buf = new uint8[length];
|
||||
uint8 *p = (uint8 *)scrap;
|
||||
uint8 *q = buf;
|
||||
for (int i=0; i<length; i++) {
|
||||
uint8 c = *p++;
|
||||
if (c < 0x80) {
|
||||
if (c == 13) // CR -> LF
|
||||
c = 10;
|
||||
} else if (!no_clip_conversion)
|
||||
c = mac2iso[c & 0x7f];
|
||||
*q++ = c;
|
||||
}
|
||||
|
||||
// Write text
|
||||
if (!PushChunk(iffw, 'FTXT', 'FORM', IFFSIZE_UNKNOWN)) {
|
||||
if (!PushChunk(iffw, 0, 'CHRS', IFFSIZE_UNKNOWN)) {
|
||||
WriteChunkBytes(iffw, scrap, length);
|
||||
PopChunk(iffw);
|
||||
}
|
||||
PopChunk(iffw);
|
||||
}
|
||||
|
||||
// Close IFF stream
|
||||
CloseIFF(iffw);
|
||||
delete[] buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,705 +0,0 @@
|
|||
/*
|
||||
* ether_amiga.cpp - Ethernet device driver, AmigaOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <exec/errors.h>
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dosextens.h>
|
||||
#include <dos/dostags.h>
|
||||
#include <devices/sana2.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <inline/exec.h>
|
||||
#include <inline/dos.h>
|
||||
#include <clib/alib_protos.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "macos_util.h"
|
||||
#include "ether.h"
|
||||
#include "ether_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define MONITOR 0
|
||||
|
||||
|
||||
// These messages are sent to the network process
|
||||
const uint32 MSG_CLEANUP = 'clea'; // Remove all protocols
|
||||
const uint32 MSG_ADD_MULTI = 'addm'; // Add multicast address
|
||||
const uint32 MSG_DEL_MULTI = 'delm'; // Add multicast address
|
||||
const uint32 MSG_ATTACH_PH = 'atph'; // Attach protocol handler
|
||||
const uint32 MSG_DETACH_PH = 'deph'; // Attach protocol handler
|
||||
const uint32 MSG_WRITE = 'writ'; // Write packet
|
||||
|
||||
struct NetMessage : public Message {
|
||||
NetMessage(uint32 what_, const struct MsgPort *reply_port)
|
||||
{
|
||||
what = what_;
|
||||
mn_ReplyPort = (struct MsgPort *)reply_port;
|
||||
mn_Length = sizeof(*this);
|
||||
}
|
||||
uint32 what;
|
||||
uint32 pointer;
|
||||
uint16 type;
|
||||
int16 result;
|
||||
};
|
||||
|
||||
|
||||
// List of attached protocols
|
||||
static const int NUM_READ_REQUESTS = 32; // Number of read requests that are sent to device in advance
|
||||
|
||||
struct NetProtocol : public Node {
|
||||
struct IOSana2Req read_io[NUM_READ_REQUESTS];
|
||||
uint8 read_buf[NUM_READ_REQUESTS][1518]; // 14 bytes header, 1500 bytes data, 4 bytes CRC
|
||||
uint16 type;
|
||||
uint32 handler;
|
||||
};
|
||||
|
||||
static struct List prot_list;
|
||||
|
||||
|
||||
// Global variables
|
||||
static struct Process *net_proc = NULL; // Network device handler process
|
||||
static bool proc_error; // Flag: process didn't initialize
|
||||
static struct MsgPort *proc_port = NULL; // Message port of process, for communication with main task
|
||||
static struct MsgPort *reply_port = NULL; // Reply port for communication with process
|
||||
static struct MsgPort *read_port = NULL; // Reply port for read IORequests (set up and owned by network process)
|
||||
|
||||
static bool write_done = false; // Flag: write request done
|
||||
|
||||
extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp)
|
||||
|
||||
|
||||
// Prototypes
|
||||
static void net_func(void);
|
||||
|
||||
|
||||
/*
|
||||
* Send message to network process
|
||||
*/
|
||||
|
||||
static int16 send_to_proc(uint32 what, uint32 pointer = 0, uint16 type = 0)
|
||||
{
|
||||
D(bug("sending %08lx to net_proc\n", what));
|
||||
NetMessage msg(what, reply_port);
|
||||
msg.pointer = pointer;
|
||||
msg.type = type;
|
||||
PutMsg(proc_port, &msg);
|
||||
WaitPort(reply_port);
|
||||
GetMsg(reply_port);
|
||||
D(bug(" sent\n"));
|
||||
return msg.result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
bool ether_init(void)
|
||||
{
|
||||
// Do nothing if no Ethernet device specified
|
||||
if (PrefsFindString("ether") == NULL)
|
||||
return false;
|
||||
|
||||
// Initialize protocol list
|
||||
NewList(&prot_list);
|
||||
|
||||
// Create message port
|
||||
reply_port = CreateMsgPort();
|
||||
if (reply_port == NULL)
|
||||
goto open_error;
|
||||
D(bug("signal mask %08lx\n", 1 << reply_port->mp_SigBit));
|
||||
|
||||
// Start process
|
||||
proc_error = false;
|
||||
SetSignal(0, SIGF_SINGLE);
|
||||
net_proc = CreateNewProcTags(
|
||||
NP_Entry, (ULONG)net_func,
|
||||
NP_Name, (ULONG)"Basilisk II Ethernet Task",
|
||||
NP_Priority, 1,
|
||||
TAG_END
|
||||
);
|
||||
if (net_proc == NULL)
|
||||
goto open_error;
|
||||
|
||||
// Wait for signal from process
|
||||
Wait(SIGF_SINGLE);
|
||||
|
||||
// Initialization error? Then bail out
|
||||
if (proc_error)
|
||||
goto open_error;
|
||||
|
||||
// Everything OK
|
||||
return true;
|
||||
|
||||
open_error:
|
||||
net_proc = NULL;
|
||||
if (reply_port) {
|
||||
DeleteMsgPort(reply_port);
|
||||
reply_port = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void ether_exit(void)
|
||||
{
|
||||
// Stop process
|
||||
if (net_proc) {
|
||||
SetSignal(0, SIGF_SINGLE);
|
||||
Signal(&net_proc->pr_Task, SIGBREAKF_CTRL_C);
|
||||
Wait(SIGF_SINGLE);
|
||||
}
|
||||
|
||||
// Delete reply port
|
||||
if (reply_port) {
|
||||
DeleteMsgPort(reply_port);
|
||||
reply_port = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset
|
||||
*/
|
||||
|
||||
void ether_reset(void)
|
||||
{
|
||||
// Remove all protocols
|
||||
if (net_proc)
|
||||
send_to_proc(MSG_CLEANUP);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add multicast address
|
||||
*/
|
||||
|
||||
int16 ether_add_multicast(uint32 pb)
|
||||
{
|
||||
return send_to_proc(MSG_ADD_MULTI, pb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete multicast address
|
||||
*/
|
||||
|
||||
int16 ether_del_multicast(uint32 pb)
|
||||
{
|
||||
return send_to_proc(MSG_DEL_MULTI, pb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Attach protocol handler
|
||||
*/
|
||||
|
||||
int16 ether_attach_ph(uint16 type, uint32 handler)
|
||||
{
|
||||
return send_to_proc(MSG_ATTACH_PH, handler, type);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Detach protocol handler
|
||||
*/
|
||||
|
||||
int16 ether_detach_ph(uint16 type)
|
||||
{
|
||||
return send_to_proc(MSG_DETACH_PH, type);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transmit raw ethernet packet
|
||||
*/
|
||||
|
||||
int16 ether_write(uint32 wds)
|
||||
{
|
||||
send_to_proc(MSG_WRITE, wds);
|
||||
return 1; // Command in progress
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove protocol from protocol list
|
||||
*/
|
||||
|
||||
static void remove_protocol(NetProtocol *p)
|
||||
{
|
||||
// Remove from list
|
||||
Forbid();
|
||||
Remove(p);
|
||||
Permit();
|
||||
|
||||
// Cancel read requests
|
||||
for (int i=0; i<NUM_READ_REQUESTS; i++) {
|
||||
AbortIO((struct IORequest *)(p->read_io + i));
|
||||
WaitIO((struct IORequest *)(p->read_io + i));
|
||||
}
|
||||
|
||||
// Free protocol struct
|
||||
FreeMem(p, sizeof(NetProtocol));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove all protocols
|
||||
*/
|
||||
|
||||
static void remove_all_protocols(void)
|
||||
{
|
||||
NetProtocol *n = (NetProtocol *)prot_list.lh_Head, *next;
|
||||
while ((next = (NetProtocol *)n->ln_Succ) != NULL) {
|
||||
remove_protocol(n);
|
||||
n = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copy received network packet to Mac side
|
||||
*/
|
||||
|
||||
static __saveds __regargs LONG copy_to_buff(uint8 *to /*a0*/, uint8 *from /*a1*/, uint32 packet_len /*d0*/)
|
||||
{
|
||||
D(bug("CopyToBuff to %08lx, from %08lx, size %08lx\n", to, from, packet_len));
|
||||
|
||||
// It would be more efficient (and take up less memory) if we
|
||||
// could invoke the packet handler from here. But we don't know
|
||||
// in what context we run, so calling Execute68k() would not be
|
||||
// a good idea, and even worse, we might run inside a hardware
|
||||
// interrupt, so we can't even trigger a Basilisk interrupt from
|
||||
// here and wait for its completion.
|
||||
CopyMem(from, to, packet_len);
|
||||
#if MONITOR
|
||||
bug("Receiving Ethernet packet:\n");
|
||||
for (int i=0; i<packet_len; i++) {
|
||||
bug("%02lx ", from[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copy data from Mac WDS to outgoing network packet
|
||||
*/
|
||||
|
||||
static __saveds __regargs LONG copy_from_buff(uint8 *to /*a0*/, char *wds /*a1*/, uint32 packet_len /*d0*/)
|
||||
{
|
||||
D(bug("CopyFromBuff to %08lx, wds %08lx, size %08lx\n", to, wds, packet_len));
|
||||
#if MONITOR
|
||||
bug("Sending Ethernet packet:\n");
|
||||
#endif
|
||||
for (;;) {
|
||||
int len = ReadMacInt16((uint32)wds);
|
||||
if (len == 0)
|
||||
break;
|
||||
#if MONITOR
|
||||
uint8 *adr = Mac2HostAddr(ReadMacInt32((uint32)wds + 2));
|
||||
for (int i=0; i<len; i++) {
|
||||
bug("%02lx ", adr[i]);
|
||||
}
|
||||
#endif
|
||||
CopyMem(Mac2HostAddr(ReadMacInt32((uint32)wds + 2)), to, len);
|
||||
to += len;
|
||||
wds += 6;
|
||||
}
|
||||
#if MONITOR
|
||||
bug("\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process for communication with the Ethernet device
|
||||
*/
|
||||
|
||||
static __saveds void net_func(void)
|
||||
{
|
||||
const char *str;
|
||||
BYTE od_error;
|
||||
struct MsgPort *write_port = NULL, *control_port = NULL;
|
||||
struct IOSana2Req *write_io = NULL, *control_io = NULL;
|
||||
bool opened = false;
|
||||
ULONG read_mask = 0, write_mask = 0, proc_port_mask = 0;
|
||||
struct Sana2DeviceQuery query_data = {sizeof(Sana2DeviceQuery)};
|
||||
ULONG buffer_tags[] = {
|
||||
S2_CopyToBuff, (uint32)copy_to_buff,
|
||||
S2_CopyFromBuff, (uint32)copy_from_buff,
|
||||
TAG_END
|
||||
};
|
||||
|
||||
// Default: error occured
|
||||
proc_error = true;
|
||||
|
||||
// Create message port for communication with main task
|
||||
proc_port = CreateMsgPort();
|
||||
if (proc_port == NULL)
|
||||
goto quit;
|
||||
proc_port_mask = 1 << proc_port->mp_SigBit;
|
||||
|
||||
// Create message ports for device I/O
|
||||
read_port = CreateMsgPort();
|
||||
if (read_port == NULL)
|
||||
goto quit;
|
||||
read_mask = 1 << read_port->mp_SigBit;
|
||||
write_port = CreateMsgPort();
|
||||
if (write_port == NULL)
|
||||
goto quit;
|
||||
write_mask = 1 << write_port->mp_SigBit;
|
||||
control_port = CreateMsgPort();
|
||||
if (control_port == NULL)
|
||||
goto quit;
|
||||
|
||||
// Create control IORequest
|
||||
control_io = (struct IOSana2Req *)CreateIORequest(control_port, sizeof(struct IOSana2Req));
|
||||
if (control_io == NULL)
|
||||
goto quit;
|
||||
control_io->ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug
|
||||
|
||||
// Parse device name
|
||||
char dev_name[256];
|
||||
ULONG dev_unit;
|
||||
|
||||
str = PrefsFindString("ether");
|
||||
if (str) {
|
||||
const char *FirstSlash = strchr(str, '/');
|
||||
const char *LastSlash = strrchr(str, '/');
|
||||
|
||||
if (FirstSlash && FirstSlash && FirstSlash != LastSlash) {
|
||||
|
||||
// Device name contains path, i.e. "Networks/xyzzy.device"
|
||||
const char *lp = str;
|
||||
char *dp = dev_name;
|
||||
|
||||
while (lp != LastSlash)
|
||||
*dp++ = *lp++;
|
||||
*dp = '\0';
|
||||
|
||||
if (strlen(dev_name) < 1)
|
||||
goto quit;
|
||||
|
||||
if (sscanf(LastSlash, "/%ld", &dev_unit) != 1)
|
||||
goto quit;
|
||||
} else {
|
||||
if (sscanf(str, "%[^/]/%ld", dev_name, &dev_unit) != 2)
|
||||
goto quit;
|
||||
}
|
||||
} else
|
||||
goto quit;
|
||||
|
||||
// Open device
|
||||
control_io->ios2_BufferManagement = buffer_tags;
|
||||
od_error = OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)control_io, 0);
|
||||
if (od_error != 0 || control_io->ios2_Req.io_Device == 0) {
|
||||
printf("WARNING: OpenDevice(<%s>, unit=%d) returned error %d)\n", (UBYTE *)dev_name, dev_unit, od_error);
|
||||
goto quit;
|
||||
}
|
||||
opened = true;
|
||||
|
||||
// Is it Ethernet?
|
||||
control_io->ios2_Req.io_Command = S2_DEVICEQUERY;
|
||||
control_io->ios2_StatData = (void *)&query_data;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
if (control_io->ios2_Req.io_Error)
|
||||
goto quit;
|
||||
if (query_data.HardwareType != S2WireType_Ethernet) {
|
||||
WarningAlert(GetString(STR_NOT_ETHERNET_WARN));
|
||||
goto quit;
|
||||
}
|
||||
|
||||
// Yes, create IORequest for writing
|
||||
write_io = (struct IOSana2Req *)CreateIORequest(write_port, sizeof(struct IOSana2Req));
|
||||
if (write_io == NULL)
|
||||
goto quit;
|
||||
memcpy(write_io, control_io, sizeof(struct IOSana2Req));
|
||||
write_io->ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug
|
||||
write_io->ios2_Req.io_Message.mn_ReplyPort = write_port;
|
||||
|
||||
// Configure Ethernet
|
||||
control_io->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
memcpy(ether_addr, control_io->ios2_DstAddr, 6);
|
||||
memcpy(control_io->ios2_SrcAddr, control_io->ios2_DstAddr, 6);
|
||||
control_io->ios2_Req.io_Command = S2_CONFIGINTERFACE;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
D(bug("Ethernet address %08lx %08lx\n", *(uint32 *)ether_addr, *(uint16 *)(ether_addr + 4)));
|
||||
|
||||
// Initialization went well, inform main task
|
||||
proc_error = false;
|
||||
Signal(MainTask, SIGF_SINGLE);
|
||||
|
||||
// Main loop
|
||||
for (;;) {
|
||||
|
||||
// Wait for I/O and messages (CTRL_C is used for quitting the task)
|
||||
ULONG sig = Wait(proc_port_mask | read_mask | write_mask | SIGBREAKF_CTRL_C);
|
||||
|
||||
// Main task wants to quit us
|
||||
if (sig & SIGBREAKF_CTRL_C)
|
||||
break;
|
||||
|
||||
// Main task sent a command to us
|
||||
if (sig & proc_port_mask) {
|
||||
struct NetMessage *msg;
|
||||
while (msg = (NetMessage *)GetMsg(proc_port)) {
|
||||
D(bug("net_proc received %08lx\n", msg->what));
|
||||
switch (msg->what) {
|
||||
case MSG_CLEANUP:
|
||||
remove_all_protocols();
|
||||
break;
|
||||
|
||||
case MSG_ADD_MULTI:
|
||||
control_io->ios2_Req.io_Command = S2_ADDMULTICASTADDRESS;
|
||||
Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6);
|
||||
DoIO((struct IORequest *)control_io);
|
||||
if (control_io->ios2_Req.io_Error == S2ERR_NOT_SUPPORTED) {
|
||||
WarningAlert(GetString(STR_NO_MULTICAST_WARN));
|
||||
msg->result = noErr;
|
||||
} else if (control_io->ios2_Req.io_Error)
|
||||
msg->result = eMultiErr;
|
||||
else
|
||||
msg->result = noErr;
|
||||
break;
|
||||
|
||||
case MSG_DEL_MULTI:
|
||||
control_io->ios2_Req.io_Command = S2_DELMULTICASTADDRESS;
|
||||
Mac2Host_memcpy(control_io->ios2_SrcAddr, msg->pointer + eMultiAddr, 6);
|
||||
DoIO((struct IORequest *)control_io);
|
||||
if (control_io->ios2_Req.io_Error)
|
||||
msg->result = eMultiErr;
|
||||
else
|
||||
msg->result = noErr;
|
||||
break;
|
||||
|
||||
case MSG_ATTACH_PH: {
|
||||
uint16 type = msg->type;
|
||||
uint32 handler = msg->pointer;
|
||||
|
||||
// Protocol of that type already installed?
|
||||
NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next;
|
||||
while ((next = (NetProtocol *)p->ln_Succ) != NULL) {
|
||||
if (p->type == type) {
|
||||
msg->result = lapProtErr;
|
||||
goto reply;
|
||||
}
|
||||
p = next;
|
||||
}
|
||||
|
||||
// Allocate NetProtocol, set type and handler
|
||||
p = (NetProtocol *)AllocMem(sizeof(NetProtocol), MEMF_PUBLIC);
|
||||
if (p == NULL) {
|
||||
msg->result = lapProtErr;
|
||||
goto reply;
|
||||
}
|
||||
p->type = type;
|
||||
p->handler = handler;
|
||||
|
||||
// Set up and submit read requests
|
||||
for (int i=0; i<NUM_READ_REQUESTS; i++) {
|
||||
memcpy(p->read_io + i, control_io, sizeof(struct IOSana2Req));
|
||||
p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Name = (char *)p; // Hide pointer to NetProtocol in node name
|
||||
p->read_io[i].ios2_Req.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug
|
||||
p->read_io[i].ios2_Req.io_Message.mn_ReplyPort = read_port;
|
||||
p->read_io[i].ios2_Req.io_Command = CMD_READ;
|
||||
p->read_io[i].ios2_PacketType = type;
|
||||
p->read_io[i].ios2_Data = p->read_buf[i];
|
||||
p->read_io[i].ios2_Req.io_Flags = SANA2IOF_RAW;
|
||||
BeginIO((struct IORequest *)(p->read_io + i));
|
||||
}
|
||||
|
||||
// Add protocol to list
|
||||
AddTail(&prot_list, p);
|
||||
|
||||
// Everything OK
|
||||
msg->result = noErr;
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_DETACH_PH: {
|
||||
uint16 type = msg->type;
|
||||
msg->result = lapProtErr;
|
||||
NetProtocol *p = (NetProtocol *)prot_list.lh_Head, *next;
|
||||
while ((next = (NetProtocol *)p->ln_Succ) != NULL) {
|
||||
if (p->type == type) {
|
||||
remove_protocol(p);
|
||||
msg->result = noErr;
|
||||
break;
|
||||
}
|
||||
p = next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_WRITE: {
|
||||
// Get pointer to Write Data Structure
|
||||
uint32 wds = msg->pointer;
|
||||
write_io->ios2_Data = (void *)wds;
|
||||
|
||||
// Calculate total packet length
|
||||
long len = 0;
|
||||
uint32 tmp = wds;
|
||||
for (;;) {
|
||||
int16 w = ReadMacInt16(tmp);
|
||||
if (w == 0)
|
||||
break;
|
||||
len += w;
|
||||
tmp += 6;
|
||||
}
|
||||
write_io->ios2_DataLength = len;
|
||||
|
||||
// Get destination address
|
||||
uint32 hdr = ReadMacInt32(wds + 2);
|
||||
Mac2Host_memcpy(write_io->ios2_DstAddr, hdr, 6);
|
||||
|
||||
// Get packet type
|
||||
uint32 type = ReadMacInt16(hdr + 12);
|
||||
if (type <= 1500)
|
||||
type = 0; // 802.3 packet
|
||||
write_io->ios2_PacketType = type;
|
||||
|
||||
// Multicast/broadcard packet?
|
||||
if (write_io->ios2_DstAddr[0] & 1) {
|
||||
if (*(uint32 *)(write_io->ios2_DstAddr) == 0xffffffff && *(uint16 *)(write_io->ios2_DstAddr + 4) == 0xffff)
|
||||
write_io->ios2_Req.io_Command = S2_BROADCAST;
|
||||
else
|
||||
write_io->ios2_Req.io_Command = S2_MULTICAST;
|
||||
} else
|
||||
write_io->ios2_Req.io_Command = CMD_WRITE;
|
||||
|
||||
// Send packet
|
||||
write_done = false;
|
||||
write_io->ios2_Req.io_Flags = SANA2IOF_RAW;
|
||||
BeginIO((IORequest *)write_io);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reply: D(bug(" net_proc replying\n"));
|
||||
ReplyMsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Packet received
|
||||
if (sig & read_mask) {
|
||||
D(bug(" packet received, triggering Ethernet interrupt\n"));
|
||||
SetInterruptFlag(INTFLAG_ETHER);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
|
||||
// Packet write completed
|
||||
if (sig & write_mask) {
|
||||
GetMsg(write_port);
|
||||
WriteMacInt32(ether_data + ed_Result, write_io->ios2_Req.io_Error ? excessCollsns : 0);
|
||||
write_done = true;
|
||||
D(bug(" packet write done, triggering Ethernet interrupt\n"));
|
||||
SetInterruptFlag(INTFLAG_ETHER);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
}
|
||||
quit:
|
||||
|
||||
// Close everything
|
||||
remove_all_protocols();
|
||||
if (opened) {
|
||||
if (CheckIO((struct IORequest *)write_io) == 0) {
|
||||
AbortIO((struct IORequest *)write_io);
|
||||
WaitIO((struct IORequest *)write_io);
|
||||
}
|
||||
CloseDevice((struct IORequest *)control_io);
|
||||
}
|
||||
if (write_io)
|
||||
DeleteIORequest(write_io);
|
||||
if (control_io)
|
||||
DeleteIORequest(control_io);
|
||||
if (control_port)
|
||||
DeleteMsgPort(control_port);
|
||||
if (write_port)
|
||||
DeleteMsgPort(write_port);
|
||||
if (read_port)
|
||||
DeleteMsgPort(read_port);
|
||||
|
||||
// Send signal to main task to confirm termination
|
||||
Forbid();
|
||||
Signal(MainTask, SIGF_SINGLE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
|
||||
*/
|
||||
|
||||
void EtherInterrupt(void)
|
||||
{
|
||||
D(bug("EtherIRQ\n"));
|
||||
|
||||
// Packet write done, enqueue DT to call IODone
|
||||
if (write_done) {
|
||||
EnqueueMac(ether_data + ed_DeferredTask, 0xd92);
|
||||
write_done = false;
|
||||
}
|
||||
|
||||
// Call protocol handler for received packets
|
||||
IOSana2Req *io;
|
||||
while (io = (struct IOSana2Req *)GetMsg(read_port)) {
|
||||
|
||||
// Get pointer to NetProtocol (hidden in node name)
|
||||
NetProtocol *p = (NetProtocol *)io->ios2_Req.io_Message.mn_Node.ln_Name;
|
||||
|
||||
// No default handler
|
||||
if (p->handler == 0)
|
||||
continue;
|
||||
|
||||
// Copy header to RHA
|
||||
Host2Mac_memcpy(ether_data + ed_RHA, io->ios2_Data, 14);
|
||||
D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12)));
|
||||
|
||||
// Call protocol handler
|
||||
M68kRegisters r;
|
||||
r.d[0] = *(uint16 *)((uint32)io->ios2_Data + 12); // Packet type
|
||||
r.d[1] = io->ios2_DataLength - 18; // Remaining packet length (without header, for ReadPacket) (-18 because the CRC is also included)
|
||||
r.a[0] = (uint32)io->ios2_Data + 14; // Pointer to packet (host address, for ReadPacket)
|
||||
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA
|
||||
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines
|
||||
D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", p->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
|
||||
Execute68k(p->handler, &r);
|
||||
|
||||
// Resend IORequest
|
||||
io->ios2_Req.io_Flags = SANA2IOF_RAW;
|
||||
BeginIO((struct IORequest *)io);
|
||||
}
|
||||
D(bug(" EtherIRQ done\n"));
|
||||
}
|
|
@ -1,387 +0,0 @@
|
|||
/*
|
||||
* extfs_amiga.cpp - MacOS file system for access native file system access, AmigaOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <exec/types.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/dos.h>
|
||||
#include <inline/dos.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "extfs.h"
|
||||
#include "extfs_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Default Finder flags
|
||||
const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void extfs_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void extfs_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add component to path name
|
||||
*/
|
||||
|
||||
void add_path_component(char *path, const char *component)
|
||||
{
|
||||
AddPart(path, (char *)component, MAX_PATH_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finder info and resource forks are kept in helper files
|
||||
*
|
||||
* Finder info:
|
||||
* /path/.finf/file
|
||||
* Resource fork:
|
||||
* /path/.rsrc/file
|
||||
*
|
||||
* The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo
|
||||
* (16+16 bytes)
|
||||
*/
|
||||
|
||||
static void make_helper_path(const char *src, char *dest, const char *add, bool only_dir = false)
|
||||
{
|
||||
dest[0] = 0;
|
||||
|
||||
// Get pointer to last component of path
|
||||
const char *last_part = FilePart((char *)src);
|
||||
|
||||
// Copy everything before
|
||||
strncpy(dest, src, last_part-src);
|
||||
dest[last_part-src] = 0;
|
||||
|
||||
// Add additional component
|
||||
AddPart(dest, (char *)add, MAX_PATH_LENGTH);
|
||||
|
||||
// Add last component
|
||||
if (!only_dir)
|
||||
AddPart(dest, (char *)last_part, MAX_PATH_LENGTH);
|
||||
}
|
||||
|
||||
static int create_helper_dir(const char *path, const char *add)
|
||||
{
|
||||
char helper_dir[MAX_PATH_LENGTH];
|
||||
make_helper_path(path, helper_dir, add, true);
|
||||
if (helper_dir[strlen(helper_dir) - 1] == '/') // Remove trailing "/"
|
||||
helper_dir[strlen(helper_dir) - 1] = 0;
|
||||
return mkdir(helper_dir, 0777);
|
||||
}
|
||||
|
||||
static int open_helper(const char *path, const char *add, int flag)
|
||||
{
|
||||
char helper_path[MAX_PATH_LENGTH];
|
||||
make_helper_path(path, helper_path, add);
|
||||
|
||||
if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
|
||||
flag |= O_CREAT;
|
||||
int fd = open(helper_path, flag, 0666);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT && (flag & O_CREAT)) {
|
||||
// One path component was missing, probably the helper
|
||||
// directory. Try to create it and re-open the file.
|
||||
int ret = create_helper_dir(path, add);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
fd = open(helper_path, flag, 0666);
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int open_finf(const char *path, int flag)
|
||||
{
|
||||
return open_helper(path, ".finf/", flag);
|
||||
}
|
||||
|
||||
static int open_rsrc(const char *path, int flag)
|
||||
{
|
||||
return open_helper(path, ".rsrc/", flag);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get/set finder type/creator for file specified by full path
|
||||
*/
|
||||
|
||||
struct ext2type {
|
||||
const char *ext;
|
||||
uint32 type;
|
||||
uint32 creator;
|
||||
};
|
||||
|
||||
static const ext2type e2t_translation[] = {
|
||||
{".z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')},
|
||||
{".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')},
|
||||
{".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
|
||||
{".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
|
||||
{".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')},
|
||||
{".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
|
||||
{".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')},
|
||||
{".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')},
|
||||
{".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
|
||||
{".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
|
||||
{".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')},
|
||||
{".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')},
|
||||
{".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')},
|
||||
{".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')},
|
||||
{".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')},
|
||||
{".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
|
||||
{".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
|
||||
{".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
|
||||
{".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
|
||||
{".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')},
|
||||
{".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')},
|
||||
{".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')},
|
||||
{".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
|
||||
{".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
|
||||
{".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
|
||||
{".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
|
||||
{".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')},
|
||||
{".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')},
|
||||
{".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')},
|
||||
{".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')},
|
||||
{".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
|
||||
{".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
|
||||
{".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
|
||||
{".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
|
||||
{".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
|
||||
{".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')},
|
||||
{".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
|
||||
{".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
|
||||
{".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
|
||||
{".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')},
|
||||
{".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')},
|
||||
{".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')},
|
||||
{".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')},
|
||||
{".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
|
||||
{".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
|
||||
{".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')},
|
||||
{NULL, 0, 0} // End marker
|
||||
};
|
||||
|
||||
void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
|
||||
{
|
||||
// Set default finder info
|
||||
Mac_memset(finfo, 0, SIZEOF_FInfo);
|
||||
if (fxinfo)
|
||||
Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
|
||||
WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
|
||||
WriteMacInt32(finfo + fdLocation, (uint32)-1);
|
||||
|
||||
// Read Finder info file
|
||||
int fd = open_finf(path, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
ssize_t actual = read(fd, Mac2HostAddr(finfo), SIZEOF_FInfo);
|
||||
if (fxinfo)
|
||||
actual += read(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo);
|
||||
close(fd);
|
||||
if (actual >= SIZEOF_FInfo)
|
||||
return;
|
||||
}
|
||||
|
||||
// No Finder info file, translate file name extension to MacOS type/creator
|
||||
if (!is_dir) {
|
||||
int path_len = strlen(path);
|
||||
for (int i=0; e2t_translation[i].ext; i++) {
|
||||
int ext_len = strlen(e2t_translation[i].ext);
|
||||
if (path_len < ext_len)
|
||||
continue;
|
||||
if (!strcasecmp(path + path_len - ext_len, e2t_translation[i].ext)) {
|
||||
WriteMacInt32(finfo + fdType, e2t_translation[i].type);
|
||||
WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
|
||||
{
|
||||
// Open Finder info file
|
||||
int fd = open_finf(path, O_RDWR);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
// Write file
|
||||
write(fd, Mac2HostAddr(finfo), SIZEOF_FInfo);
|
||||
if (fxinfo)
|
||||
write(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resource fork emulation functions
|
||||
*/
|
||||
|
||||
uint32 get_rfork_size(const char *path)
|
||||
{
|
||||
// Open resource file
|
||||
int fd = open_rsrc(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
// Get size
|
||||
off_t size = lseek(fd, 0, SEEK_END);
|
||||
|
||||
// Close file and return size
|
||||
close(fd);
|
||||
return size < 0 ? 0 : size;
|
||||
}
|
||||
|
||||
int open_rfork(const char *path, int flag)
|
||||
{
|
||||
return open_rsrc(path, flag);
|
||||
}
|
||||
|
||||
void close_rfork(const char *path, int fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read "length" bytes from file to "buffer",
|
||||
* returns number of bytes read (or -1 on error)
|
||||
*/
|
||||
|
||||
ssize_t extfs_read(int fd, void *buffer, size_t length)
|
||||
{
|
||||
return read(fd, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write "length" bytes from "buffer" to file,
|
||||
* returns number of bytes written (or -1 on error)
|
||||
*/
|
||||
|
||||
ssize_t extfs_write(int fd, void *buffer, size_t length)
|
||||
{
|
||||
return write(fd, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove file/directory (and associated helper files),
|
||||
* returns false on error (and sets errno)
|
||||
*/
|
||||
|
||||
bool extfs_remove(const char *path)
|
||||
{
|
||||
// Remove helpers first, don't complain if this fails
|
||||
char helper_path[MAX_PATH_LENGTH];
|
||||
make_helper_path(path, helper_path, ".finf/", false);
|
||||
remove(helper_path);
|
||||
make_helper_path(path, helper_path, ".rsrc/", false);
|
||||
remove(helper_path);
|
||||
|
||||
// Now remove file or directory (and helper directories in the directory)
|
||||
if (remove(path) < 0) {
|
||||
if (errno == EISDIR || errno == ENOTEMPTY) {
|
||||
helper_path[0] = 0;
|
||||
strncpy(helper_path, path, MAX_PATH_LENGTH-1);
|
||||
add_path_component(helper_path, ".finf");
|
||||
rmdir(helper_path);
|
||||
helper_path[0] = 0;
|
||||
strncpy(helper_path, path, MAX_PATH_LENGTH-1);
|
||||
add_path_component(helper_path, ".rsrc");
|
||||
rmdir(helper_path);
|
||||
return rmdir(path) == 0;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rename/move file/directory (and associated helper files),
|
||||
* returns false on error (and sets errno)
|
||||
*/
|
||||
|
||||
bool extfs_rename(const char *old_path, const char *new_path)
|
||||
{
|
||||
// Rename helpers first, don't complain if this fails
|
||||
char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
|
||||
make_helper_path(old_path, old_helper_path, ".finf/", false);
|
||||
make_helper_path(new_path, new_helper_path, ".finf/", false);
|
||||
create_helper_dir(new_path, ".finf/");
|
||||
rename(old_helper_path, new_helper_path);
|
||||
make_helper_path(old_path, old_helper_path, ".rsrc/", false);
|
||||
make_helper_path(new_path, new_helper_path, ".rsrc/", false);
|
||||
create_helper_dir(new_path, ".rsrc/");
|
||||
rename(old_helper_path, new_helper_path);
|
||||
|
||||
// Now rename file
|
||||
return rename(old_path, new_path) == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ftruncate() is missing from libnix
|
||||
*/
|
||||
|
||||
extern unsigned long *__stdfiledes;
|
||||
|
||||
int ftruncate(int fd, off_t size)
|
||||
{
|
||||
if (SetFileSize(__stdfiledes[fd], size, OFFSET_BEGINNING) < 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
|
@ -1,743 +0,0 @@
|
|||
/*
|
||||
* main_amiga.cpp - Startup code for AmigaOS
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <exec/execbase.h>
|
||||
#include <exec/memory.h>
|
||||
#include <exec/tasks.h>
|
||||
#include <dos/dostags.h>
|
||||
#include <intuition/intuition.h>
|
||||
#include <devices/timer.h>
|
||||
#include <devices/ahi.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <proto/intuition.h>
|
||||
#include <inline/exec.h>
|
||||
#include <inline/dos.h>
|
||||
#include <inline/intuition.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "xpram.h"
|
||||
#include "timer.h"
|
||||
#include "sony.h"
|
||||
#include "disk.h"
|
||||
#include "cdrom.h"
|
||||
#include "scsi.h"
|
||||
#include "audio.h"
|
||||
#include "video.h"
|
||||
#include "serial.h"
|
||||
#include "ether.h"
|
||||
#include "clip.h"
|
||||
#include "emul_op.h"
|
||||
#include "rom_patches.h"
|
||||
#include "prefs.h"
|
||||
#include "prefs_editor.h"
|
||||
#include "sys.h"
|
||||
#include "user_strings.h"
|
||||
#include "version.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Options for libnix
|
||||
unsigned long __stack = 0x4000; // Stack requirement
|
||||
int __nocommandline = 1; // Disable command line parsing
|
||||
|
||||
|
||||
// Constants
|
||||
static const char ROM_FILE_NAME[] = "ROM";
|
||||
static const char __ver[] = "$VER: " VERSION_STRING " " __DATE__;
|
||||
static const int SCRATCH_MEM_SIZE = 65536;
|
||||
|
||||
|
||||
// RAM and ROM pointers
|
||||
uint32 RAMBaseMac; // RAM base (Mac address space)
|
||||
uint8 *RAMBaseHost; // RAM base (host address space)
|
||||
uint32 RAMSize; // Size of RAM
|
||||
uint32 ROMBaseMac; // ROM base (Mac address space)
|
||||
uint8 *ROMBaseHost; // ROM base (host address space)
|
||||
uint32 ROMSize; // Size of ROM
|
||||
|
||||
|
||||
// CPU and FPU type, addressing mode
|
||||
int CPUType;
|
||||
bool CPUIs68060;
|
||||
int FPUType;
|
||||
bool TwentyFourBitAddressing;
|
||||
|
||||
|
||||
// Global variables
|
||||
extern ExecBase *SysBase;
|
||||
struct Library *GfxBase = NULL;
|
||||
struct IntuitionBase *IntuitionBase = NULL;
|
||||
struct Library *GadToolsBase = NULL;
|
||||
struct Library *IFFParseBase = NULL;
|
||||
struct Library *AslBase = NULL;
|
||||
struct Library *P96Base = NULL;
|
||||
struct Library *CyberGfxBase = NULL;
|
||||
struct Library *TimerBase = NULL;
|
||||
struct Library *AHIBase = NULL;
|
||||
struct Library *DiskBase = NULL;
|
||||
|
||||
struct Task *MainTask; // Our task
|
||||
uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes
|
||||
APTR OldTrapHandler = NULL; // Old trap handler
|
||||
APTR OldExceptionHandler = NULL; // Old exception handler
|
||||
BYTE IRQSig = -1; // "Interrupt" signal number
|
||||
ULONG IRQSigMask = 0; // "Interrupt" signal mask
|
||||
|
||||
static struct timerequest *timereq = NULL; // IORequest for timer
|
||||
|
||||
static struct MsgPort *ahi_port = NULL; // Port for AHI
|
||||
static struct AHIRequest *ahi_io = NULL; // IORequest for AHI
|
||||
|
||||
static struct Process *xpram_proc = NULL; // XPRAM watchdog
|
||||
static volatile bool xpram_proc_active = true; // Flag for quitting the XPRAM watchdog
|
||||
|
||||
static struct Process *tick_proc = NULL; // 60Hz process
|
||||
static volatile bool tick_proc_active = true; // Flag for quitting the 60Hz process
|
||||
|
||||
static bool stack_swapped = false; // Stack swapping
|
||||
static StackSwapStruct stack_swap;
|
||||
|
||||
|
||||
// Assembly functions
|
||||
struct trap_regs;
|
||||
extern "C" void AtomicAnd(uint32 *p, uint32 val);
|
||||
extern "C" void AtomicOr(uint32 *p, uint32 val);
|
||||
extern "C" void MoveVBR(void);
|
||||
extern "C" void DisableSuperBypass(void);
|
||||
extern "C" void TrapHandlerAsm(void);
|
||||
extern "C" void ExceptionHandlerAsm(void);
|
||||
extern "C" void IllInstrHandler(trap_regs *regs);
|
||||
extern "C" void PrivViolHandler(trap_regs *regs);
|
||||
extern "C" void quit_emulator(void);
|
||||
extern "C" void AsmTriggerNMI(void);
|
||||
uint16 EmulatedSR; // Emulated SR (supervisor bit and interrupt mask)
|
||||
|
||||
|
||||
// Prototypes
|
||||
static void jump_to_rom(void);
|
||||
static void xpram_func(void);
|
||||
static void tick_func(void);
|
||||
|
||||
|
||||
/*
|
||||
* Main program
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Initialize variables
|
||||
RAMBaseHost = NULL;
|
||||
ROMBaseHost = NULL;
|
||||
MainTask = FindTask(NULL);
|
||||
struct DateStamp ds;
|
||||
DateStamp(&ds);
|
||||
srand(ds.ds_Tick);
|
||||
|
||||
// Print some info
|
||||
printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
|
||||
printf(" %s\n", GetString(STR_ABOUT_TEXT2));
|
||||
|
||||
// Open libraries
|
||||
GfxBase = OpenLibrary((UBYTE *) "graphics.library", 39);
|
||||
if (GfxBase == NULL) {
|
||||
printf("Cannot open graphics.library V39.\n");
|
||||
exit(1);
|
||||
}
|
||||
IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *) "intuition.library", 39);
|
||||
if (IntuitionBase == NULL) {
|
||||
printf("Cannot open intuition.library V39.\n");
|
||||
CloseLibrary(GfxBase);
|
||||
exit(1);
|
||||
}
|
||||
DiskBase = (struct Library *)OpenResource((UBYTE *) "disk.resource");
|
||||
if (DiskBase == NULL)
|
||||
QuitEmulator();
|
||||
GadToolsBase = OpenLibrary((UBYTE *) "gadtools.library", 39);
|
||||
if (GadToolsBase == NULL) {
|
||||
ErrorAlert(STR_NO_GADTOOLS_LIB_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
IFFParseBase = OpenLibrary((UBYTE *) "iffparse.library", 39);
|
||||
if (IFFParseBase == NULL) {
|
||||
ErrorAlert(STR_NO_IFFPARSE_LIB_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
AslBase = OpenLibrary((UBYTE *) "asl.library", 36);
|
||||
if (AslBase == NULL) {
|
||||
ErrorAlert(STR_NO_ASL_LIB_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
|
||||
if (FindTask((UBYTE *) "« Enforcer »")) {
|
||||
ErrorAlert(STR_ENFORCER_RUNNING_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
|
||||
// These two can fail (the respective gfx support won't be available, then)
|
||||
P96Base = OpenLibrary((UBYTE *) "Picasso96API.library", 2);
|
||||
CyberGfxBase = OpenLibrary((UBYTE *) "cybergraphics.library", 2);
|
||||
|
||||
// Read preferences
|
||||
PrefsInit(NULL, argc, argv);
|
||||
|
||||
// Open AHI
|
||||
ahi_port = CreateMsgPort();
|
||||
if (ahi_port) {
|
||||
ahi_io = (struct AHIRequest *)CreateIORequest(ahi_port, sizeof(struct AHIRequest));
|
||||
if (ahi_io) {
|
||||
ahi_io->ahir_Version = 2;
|
||||
if (OpenDevice((UBYTE *) AHINAME, AHI_NO_UNIT, (struct IORequest *)ahi_io, 0) == 0) {
|
||||
AHIBase = (struct Library *)ahi_io->ahir_Std.io_Device;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init system routines
|
||||
SysInit();
|
||||
|
||||
// Show preferences editor
|
||||
if (!PrefsFindBool("nogui"))
|
||||
if (!PrefsEditor())
|
||||
QuitEmulator();
|
||||
|
||||
// Check start of Chip memory (because we need access to 0x0000..0x2000)
|
||||
if ((uint32)FindName(&SysBase->MemList, (UBYTE *) "chip memory") < 0x2000) {
|
||||
ErrorAlert(STR_NO_PREPARE_EMUL_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
|
||||
// Open timer.device
|
||||
timereq = (struct timerequest *)AllocVec(sizeof(timerequest), MEMF_PUBLIC | MEMF_CLEAR);
|
||||
if (timereq == NULL) {
|
||||
ErrorAlert(STR_NO_MEM_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
if (OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timereq, 0)) {
|
||||
ErrorAlert(STR_NO_TIMER_DEV_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
TimerBase = (struct Library *)timereq->tr_node.io_Device;
|
||||
|
||||
// Allocate scratch memory
|
||||
ScratchMem = (uint8 *)AllocMem(SCRATCH_MEM_SIZE, MEMF_PUBLIC);
|
||||
if (ScratchMem == NULL) {
|
||||
ErrorAlert(STR_NO_MEM_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
ScratchMem += SCRATCH_MEM_SIZE/2; // ScratchMem points to middle of block
|
||||
|
||||
// Create area for Mac RAM and ROM (ROM must be higher in memory,
|
||||
// so we allocate one big chunk and put the ROM at the top of it)
|
||||
RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
|
||||
if (RAMSize < 1024*1024) {
|
||||
WarningAlert(GetString(STR_SMALL_RAM_WARN));
|
||||
RAMSize = 1024*1024;
|
||||
}
|
||||
RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC);
|
||||
if (RAMBaseHost == NULL) {
|
||||
uint32 newRAMSize = AvailMem(MEMF_LARGEST) - 0x100000;
|
||||
char xText[120];
|
||||
|
||||
sprintf(xText, GetString(STR_NOT_ENOUGH_MEM_WARN), RAMSize, newRAMSize);
|
||||
|
||||
if (ChoiceAlert(xText, "Use", "Quit") != 1)
|
||||
QuitEmulator();
|
||||
|
||||
RAMSize = newRAMSize;
|
||||
RAMBaseHost = (uint8 *)AllocVec(RAMSize - 0x100000, MEMF_PUBLIC);
|
||||
if (RAMBaseHost == NULL) {
|
||||
ErrorAlert(STR_NO_MEM_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
}
|
||||
RAMBaseMac = (uint32)RAMBaseHost;
|
||||
D(bug("Mac RAM starts at %08lx\n", RAMBaseHost));
|
||||
ROMBaseHost = RAMBaseHost + RAMSize;
|
||||
ROMBaseMac = (uint32)ROMBaseHost;
|
||||
D(bug("Mac ROM starts at %08lx\n", ROMBaseHost));
|
||||
|
||||
// Get rom file path from preferences
|
||||
const char *rom_path = PrefsFindString("rom");
|
||||
|
||||
// Load Mac ROM
|
||||
BPTR rom_fh = Open(rom_path ? (char *)rom_path : (char *)ROM_FILE_NAME, MODE_OLDFILE);
|
||||
if (rom_fh == 0) {
|
||||
ErrorAlert(STR_NO_ROM_FILE_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
printf(GetString(STR_READING_ROM_FILE));
|
||||
Seek(rom_fh, 0, OFFSET_END);
|
||||
ROMSize = Seek(rom_fh, 0, OFFSET_CURRENT);
|
||||
if (ROMSize != 512*1024 && ROMSize != 1024*1024) {
|
||||
ErrorAlert(STR_ROM_SIZE_ERR);
|
||||
Close(rom_fh);
|
||||
QuitEmulator();
|
||||
}
|
||||
Seek(rom_fh, 0, OFFSET_BEGINNING);
|
||||
if (Read(rom_fh, ROMBaseHost, ROMSize) != ROMSize) {
|
||||
ErrorAlert(STR_ROM_FILE_READ_ERR);
|
||||
Close(rom_fh);
|
||||
QuitEmulator();
|
||||
}
|
||||
|
||||
// Set CPU and FPU type
|
||||
UWORD attn = SysBase->AttnFlags;
|
||||
CPUType = attn & AFF_68040 ? 4 : (attn & AFF_68030 ? 3 : 2);
|
||||
CPUIs68060 = attn & AFF_68060;
|
||||
FPUType = attn & AFF_68881 ? 1 : 0;
|
||||
|
||||
// Initialize everything
|
||||
if (!InitAll(NULL))
|
||||
QuitEmulator();
|
||||
|
||||
// Move VBR away from 0 if neccessary
|
||||
MoveVBR();
|
||||
|
||||
// On 68060, disable Super Bypass mode because of a CPU bug that is triggered by MacOS 8
|
||||
if (CPUIs68060)
|
||||
DisableSuperBypass();
|
||||
|
||||
memset((UBYTE *) 8, 0, 0x2000-8);
|
||||
|
||||
// Install trap handler
|
||||
EmulatedSR = 0x2700;
|
||||
OldTrapHandler = MainTask->tc_TrapCode;
|
||||
MainTask->tc_TrapCode = (APTR)TrapHandlerAsm;
|
||||
|
||||
// Allocate signal for interrupt emulation and install exception handler
|
||||
IRQSig = AllocSignal(-1);
|
||||
IRQSigMask = 1 << IRQSig;
|
||||
OldExceptionHandler = MainTask->tc_ExceptCode;
|
||||
MainTask->tc_ExceptCode = (APTR)ExceptionHandlerAsm;
|
||||
SetExcept(SIGBREAKF_CTRL_C | IRQSigMask, SIGBREAKF_CTRL_C | IRQSigMask);
|
||||
|
||||
// Start XPRAM watchdog process
|
||||
xpram_proc = CreateNewProcTags(
|
||||
NP_Entry, (ULONG)xpram_func,
|
||||
NP_Name, (ULONG)"Basilisk II XPRAM Watchdog",
|
||||
NP_Priority, 0,
|
||||
TAG_END
|
||||
);
|
||||
|
||||
// Start 60Hz process
|
||||
tick_proc = CreateNewProcTags(
|
||||
NP_Entry, (ULONG)tick_func,
|
||||
NP_Name, (ULONG)"Basilisk II 60Hz",
|
||||
NP_Priority, 5,
|
||||
TAG_END
|
||||
);
|
||||
|
||||
// Set task priority to -1 so we don't use all processing time
|
||||
SetTaskPri(MainTask, -1);
|
||||
|
||||
WriteMacInt32(0xbff, 0); // MacsBugFlags
|
||||
|
||||
// Swap stack to Mac RAM area
|
||||
stack_swap.stk_Lower = RAMBaseHost;
|
||||
stack_swap.stk_Upper = (ULONG)RAMBaseHost + RAMSize;
|
||||
stack_swap.stk_Pointer = RAMBaseHost + 0x8000;
|
||||
StackSwap(&stack_swap);
|
||||
stack_swapped = true;
|
||||
|
||||
// Jump to ROM boot routine
|
||||
Start680x0();
|
||||
|
||||
QuitEmulator();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Start680x0(void)
|
||||
{
|
||||
typedef void (*rom_func)(void);
|
||||
rom_func fp = (rom_func)(ROMBaseHost + 0x2a);
|
||||
fp();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Quit emulator (__saveds because it might be called from an exception)
|
||||
*/
|
||||
|
||||
// Assembly entry point
|
||||
void __saveds quit_emulator(void)
|
||||
{
|
||||
QuitEmulator();
|
||||
}
|
||||
|
||||
void QuitEmulator(void)
|
||||
{
|
||||
// Stop 60Hz process
|
||||
if (tick_proc) {
|
||||
SetSignal(0, SIGF_SINGLE);
|
||||
tick_proc_active = false;
|
||||
Wait(SIGF_SINGLE);
|
||||
}
|
||||
|
||||
// Stop XPRAM watchdog process
|
||||
if (xpram_proc) {
|
||||
SetSignal(0, SIGF_SINGLE);
|
||||
xpram_proc_active = false;
|
||||
Wait(SIGF_SINGLE);
|
||||
}
|
||||
|
||||
// Restore stack
|
||||
if (stack_swapped) {
|
||||
stack_swapped = false;
|
||||
StackSwap(&stack_swap);
|
||||
}
|
||||
|
||||
// Remove exception handler
|
||||
if (IRQSig >= 0) {
|
||||
SetExcept(0, SIGBREAKF_CTRL_C | IRQSigMask);
|
||||
MainTask->tc_ExceptCode = OldExceptionHandler;
|
||||
FreeSignal(IRQSig);
|
||||
}
|
||||
|
||||
// Remove trap handler
|
||||
MainTask->tc_TrapCode = OldTrapHandler;
|
||||
|
||||
// Deinitialize everything
|
||||
ExitAll();
|
||||
|
||||
// Delete RAM/ROM area
|
||||
if (RAMBaseHost)
|
||||
FreeVec(RAMBaseHost);
|
||||
|
||||
// Delete scratch memory area
|
||||
if (ScratchMem)
|
||||
FreeMem((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
|
||||
|
||||
// Close timer.device
|
||||
if (TimerBase)
|
||||
CloseDevice((struct IORequest *)timereq);
|
||||
if (timereq)
|
||||
FreeVec(timereq);
|
||||
|
||||
// Exit system routines
|
||||
SysExit();
|
||||
|
||||
// Close AHI
|
||||
if (AHIBase)
|
||||
CloseDevice((struct IORequest *)ahi_io);
|
||||
if (ahi_io)
|
||||
DeleteIORequest((struct IORequest *)ahi_io);
|
||||
if (ahi_port)
|
||||
DeleteMsgPort(ahi_port);
|
||||
|
||||
// Exit preferences
|
||||
PrefsExit();
|
||||
|
||||
// Close libraries
|
||||
if (CyberGfxBase)
|
||||
CloseLibrary(CyberGfxBase);
|
||||
if (P96Base)
|
||||
CloseLibrary(P96Base);
|
||||
if (AslBase)
|
||||
CloseLibrary(AslBase);
|
||||
if (IFFParseBase)
|
||||
CloseLibrary(IFFParseBase);
|
||||
if (GadToolsBase)
|
||||
CloseLibrary(GadToolsBase);
|
||||
if (IntuitionBase)
|
||||
CloseLibrary((struct Library *)IntuitionBase);
|
||||
if (GfxBase)
|
||||
CloseLibrary(GfxBase);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Code was patched, flush caches if neccessary (i.e. when using a real 680x0
|
||||
* or a dynamically recompiling emulator)
|
||||
*/
|
||||
|
||||
void FlushCodeCache(void *start, uint32 size)
|
||||
{
|
||||
CacheClearE(start, size, CACRF_ClearI | CACRF_ClearD);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mutexes
|
||||
*/
|
||||
|
||||
struct B2_mutex {
|
||||
int dummy; //!!
|
||||
};
|
||||
|
||||
B2_mutex *B2_create_mutex(void)
|
||||
{
|
||||
return new B2_mutex;
|
||||
}
|
||||
|
||||
void B2_lock_mutex(B2_mutex *mutex)
|
||||
{
|
||||
}
|
||||
|
||||
void B2_unlock_mutex(B2_mutex *mutex)
|
||||
{
|
||||
}
|
||||
|
||||
void B2_delete_mutex(B2_mutex *mutex)
|
||||
{
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt flags (must be handled atomically!)
|
||||
*/
|
||||
|
||||
uint32 InterruptFlags;
|
||||
|
||||
void SetInterruptFlag(uint32 flag)
|
||||
{
|
||||
AtomicOr(&InterruptFlags, flag);
|
||||
}
|
||||
|
||||
void ClearInterruptFlag(uint32 flag)
|
||||
{
|
||||
AtomicAnd(&InterruptFlags, ~flag);
|
||||
}
|
||||
|
||||
void TriggerInterrupt(void)
|
||||
{
|
||||
Signal(MainTask, IRQSigMask);
|
||||
}
|
||||
|
||||
void TriggerNMI(void)
|
||||
{
|
||||
AsmTriggerNMI();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 60Hz thread (really 60.15Hz)
|
||||
*/
|
||||
|
||||
static __saveds void tick_func(void)
|
||||
{
|
||||
int tick_counter = 0;
|
||||
struct MsgPort *timer_port = NULL;
|
||||
struct timerequest *timer_io = NULL;
|
||||
ULONG timer_mask = 0;
|
||||
|
||||
// Start 60Hz timer
|
||||
timer_port = CreateMsgPort();
|
||||
if (timer_port) {
|
||||
timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
|
||||
if (timer_io) {
|
||||
if (!OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
|
||||
timer_mask = 1 << timer_port->mp_SigBit;
|
||||
timer_io->tr_node.io_Command = TR_ADDREQUEST;
|
||||
timer_io->tr_time.tv_secs = 0;
|
||||
timer_io->tr_time.tv_micro = 16625;
|
||||
SendIO((struct IORequest *)timer_io);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (tick_proc_active) {
|
||||
|
||||
// Wait for timer tick
|
||||
Wait(timer_mask);
|
||||
|
||||
// Restart timer
|
||||
timer_io->tr_node.io_Command = TR_ADDREQUEST;
|
||||
timer_io->tr_time.tv_secs = 0;
|
||||
timer_io->tr_time.tv_micro = 16625;
|
||||
SendIO((struct IORequest *)timer_io);
|
||||
|
||||
// Pseudo Mac 1Hz interrupt, update local time
|
||||
if (++tick_counter > 60) {
|
||||
tick_counter = 0;
|
||||
WriteMacInt32(0x20c, TimerDateTime());
|
||||
SetInterruptFlag(INTFLAG_1HZ);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
|
||||
// Trigger 60Hz interrupt
|
||||
SetInterruptFlag(INTFLAG_60HZ);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
|
||||
// Stop timer
|
||||
if (timer_io) {
|
||||
if (!CheckIO((struct IORequest *)timer_io))
|
||||
AbortIO((struct IORequest *)timer_io);
|
||||
WaitIO((struct IORequest *)timer_io);
|
||||
CloseDevice((struct IORequest *)timer_io);
|
||||
DeleteIORequest(timer_io);
|
||||
}
|
||||
if (timer_port)
|
||||
DeleteMsgPort(timer_port);
|
||||
|
||||
// Main task asked for termination, send signal
|
||||
Forbid();
|
||||
Signal(MainTask, SIGF_SINGLE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XPRAM watchdog thread (saves XPRAM every minute)
|
||||
*/
|
||||
|
||||
static __saveds void xpram_func(void)
|
||||
{
|
||||
uint8 last_xpram[XPRAM_SIZE];
|
||||
memcpy(last_xpram, XPRAM, XPRAM_SIZE);
|
||||
|
||||
while (xpram_proc_active) {
|
||||
for (int i=0; i<60 && xpram_proc_active; i++)
|
||||
Delay(50); // Only wait 1 second so we quit promptly when xpram_proc_active becomes false
|
||||
if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
|
||||
memcpy(last_xpram, XPRAM, XPRAM_SIZE);
|
||||
SaveXPRAM();
|
||||
}
|
||||
}
|
||||
|
||||
// Main task asked for termination, send signal
|
||||
Forbid();
|
||||
Signal(MainTask, SIGF_SINGLE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display error alert
|
||||
*/
|
||||
|
||||
void ErrorAlert(const char *text)
|
||||
{
|
||||
if (PrefsFindBool("nogui")) {
|
||||
printf(GetString(STR_SHELL_ERROR_PREFIX), text);
|
||||
return;
|
||||
}
|
||||
EasyStruct req;
|
||||
req.es_StructSize = sizeof(EasyStruct);
|
||||
req.es_Flags = 0;
|
||||
req.es_Title = (UBYTE *)GetString(STR_ERROR_ALERT_TITLE);
|
||||
req.es_TextFormat = (UBYTE *)GetString(STR_GUI_ERROR_PREFIX);
|
||||
req.es_GadgetFormat = (UBYTE *)GetString(STR_QUIT_BUTTON);
|
||||
EasyRequest(NULL, &req, NULL, (ULONG)text);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display warning alert
|
||||
*/
|
||||
|
||||
void WarningAlert(const char *text)
|
||||
{
|
||||
if (PrefsFindBool("nogui")) {
|
||||
printf(GetString(STR_SHELL_WARNING_PREFIX), text);
|
||||
return;
|
||||
}
|
||||
EasyStruct req;
|
||||
req.es_StructSize = sizeof(EasyStruct);
|
||||
req.es_Flags = 0;
|
||||
req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE);
|
||||
req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX);
|
||||
req.es_GadgetFormat = (UBYTE *)GetString(STR_OK_BUTTON);
|
||||
EasyRequest(NULL, &req, NULL, (ULONG)text);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display choice alert
|
||||
*/
|
||||
|
||||
bool ChoiceAlert(const char *text, const char *pos, const char *neg)
|
||||
{
|
||||
char str[256];
|
||||
sprintf(str, "%s|%s", pos, neg);
|
||||
EasyStruct req;
|
||||
req.es_StructSize = sizeof(EasyStruct);
|
||||
req.es_Flags = 0;
|
||||
req.es_Title = (UBYTE *)GetString(STR_WARNING_ALERT_TITLE);
|
||||
req.es_TextFormat = (UBYTE *)GetString(STR_GUI_WARNING_PREFIX);
|
||||
req.es_GadgetFormat = (UBYTE *)str;
|
||||
return EasyRequest(NULL, &req, NULL, (ULONG)text);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Illegal Instruction and Privilege Violation trap handlers
|
||||
*/
|
||||
|
||||
struct trap_regs { // This must match the layout of M68kRegisters
|
||||
uint32 d[8];
|
||||
uint32 a[8];
|
||||
uint16 sr;
|
||||
uint32 pc;
|
||||
};
|
||||
|
||||
void __saveds IllInstrHandler(trap_regs *r)
|
||||
{
|
||||
// D(bug("IllInstrHandler/%ld\n", __LINE__));
|
||||
|
||||
uint16 opcode = *(uint16 *)(r->pc);
|
||||
if ((opcode & 0xff00) != 0x7100) {
|
||||
printf("Illegal Instruction %04x at %08lx\n", *(uint16 *)(r->pc), r->pc);
|
||||
printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
|
||||
"d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
|
||||
"a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
|
||||
"a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
|
||||
"sr %04x\n",
|
||||
r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
|
||||
r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
|
||||
r->sr);
|
||||
QuitEmulator();
|
||||
} else {
|
||||
// Disable interrupts
|
||||
uint16 sr = EmulatedSR;
|
||||
EmulatedSR |= 0x0700;
|
||||
|
||||
// Call opcode routine
|
||||
EmulOp(opcode, (M68kRegisters *)r);
|
||||
r->pc += 2;
|
||||
|
||||
// Restore interrupts
|
||||
EmulatedSR = sr;
|
||||
if ((EmulatedSR & 0x0700) == 0 && InterruptFlags)
|
||||
Signal(MainTask, IRQSigMask);
|
||||
}
|
||||
}
|
||||
|
||||
void __saveds PrivViolHandler(trap_regs *r)
|
||||
{
|
||||
printf("Privileged instruction %04x %04x at %08lx\n", *(uint16 *)(r->pc), *(uint16 *)(r->pc + 2), r->pc);
|
||||
printf("d0 %08lx d1 %08lx d2 %08lx d3 %08lx\n"
|
||||
"d4 %08lx d5 %08lx d6 %08lx d7 %08lx\n"
|
||||
"a0 %08lx a1 %08lx a2 %08lx a3 %08lx\n"
|
||||
"a4 %08lx a5 %08lx a6 %08lx a7 %08lx\n"
|
||||
"sr %04x\n",
|
||||
r->d[0], r->d[1], r->d[2], r->d[3], r->d[4], r->d[5], r->d[6], r->d[7],
|
||||
r->a[0], r->a[1], r->a[2], r->a[3], r->a[4], r->a[5], r->a[6], r->a[7],
|
||||
r->sr);
|
||||
QuitEmulator();
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* prefs_amiga.cpp - Preferences handling, AmigaOS specifix stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "prefs.h"
|
||||
|
||||
|
||||
// Platform-specific preferences items
|
||||
prefs_desc platform_prefs_items[] = {
|
||||
{"sound", TYPE_STRING, false, "sound output mode description"},
|
||||
{"scsimemtype", TYPE_INT32, false, "SCSI buffer memory type"},
|
||||
{NULL, TYPE_END, false, NULL} // End of list
|
||||
};
|
||||
|
||||
|
||||
// Prefs file name
|
||||
const char PREFS_FILE_NAME[] = "ENV:BasiliskII_prefs";
|
||||
const char PREFS_FILE_NAME_ARC[] = "ENVARC:BasiliskII_prefs";
|
||||
|
||||
|
||||
/*
|
||||
* Load preferences from settings file
|
||||
*/
|
||||
|
||||
void LoadPrefs(void)
|
||||
{
|
||||
// Read preferences from settings file
|
||||
FILE *f = fopen(PREFS_FILE_NAME, "r");
|
||||
if (f != NULL) {
|
||||
|
||||
// Prefs file found, load settings
|
||||
LoadPrefsFromStream(f);
|
||||
fclose(f);
|
||||
|
||||
} else {
|
||||
|
||||
// No prefs file, save defaults
|
||||
SavePrefs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save preferences to settings file
|
||||
*/
|
||||
|
||||
void SavePrefs(void)
|
||||
{
|
||||
FILE *f;
|
||||
if ((f = fopen(PREFS_FILE_NAME, "w")) != NULL) {
|
||||
SavePrefsToStream(f);
|
||||
fclose(f);
|
||||
}
|
||||
if ((f = fopen(PREFS_FILE_NAME_ARC, "w")) != NULL) {
|
||||
SavePrefsToStream(f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add defaults of platform-specific prefs items
|
||||
* You may also override the defaults set in PrefsInit()
|
||||
*/
|
||||
|
||||
void AddPlatformPrefsDefaults(void)
|
||||
{
|
||||
PrefsReplaceString("extfs", "WORK:");
|
||||
PrefsAddInt32("scsimemtype", 0);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,289 +0,0 @@
|
|||
/*
|
||||
* scsi_amiga.cpp - SCSI Manager, Amiga specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <devices/trackdisk.h>
|
||||
#include <devices/scsidisk.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/exec.h>
|
||||
#include <inline/exec.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "scsi.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Global variables
|
||||
static struct SCSICmd scsi;
|
||||
|
||||
static IOStdReq *ios[8*8]; // IORequests for 8 units and 8 LUNs each
|
||||
static IOStdReq *io; // Active IORequest (selected target)
|
||||
|
||||
static struct MsgPort *the_port = NULL; // Message port for device communication
|
||||
|
||||
static ULONG buffer_size; // Size of data buffer
|
||||
static UBYTE *buffer = NULL; // Pointer to data buffer
|
||||
static ULONG buffer_memf; // Buffer memory flags
|
||||
|
||||
static UBYTE cmd_buffer[12]; // Buffer for SCSI command
|
||||
|
||||
const int SENSE_LENGTH = 256;
|
||||
static UBYTE *sense_buffer = NULL; // Buffer for autosense data
|
||||
|
||||
static bool direct_transfers_supported = false; // Direct data transfers (bypassing the buffer) are supported
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void SCSIInit(void)
|
||||
{
|
||||
int id, lun;
|
||||
|
||||
int memtype = PrefsFindInt32("scsimemtype");
|
||||
switch (memtype) {
|
||||
case 1:
|
||||
buffer_memf = MEMF_24BITDMA | MEMF_PUBLIC;
|
||||
break;
|
||||
case 2:
|
||||
buffer_memf = MEMF_ANY | MEMF_PUBLIC;
|
||||
direct_transfers_supported = true;
|
||||
break;
|
||||
default:
|
||||
buffer_memf = MEMF_CHIP | MEMF_PUBLIC;
|
||||
break;
|
||||
}
|
||||
|
||||
// Create port and buffers
|
||||
the_port = CreateMsgPort();
|
||||
buffer = (UBYTE *)AllocMem(buffer_size = 0x10000, buffer_memf);
|
||||
sense_buffer = (UBYTE *)AllocMem(SENSE_LENGTH, MEMF_CHIP | MEMF_PUBLIC);
|
||||
if (the_port == NULL || buffer == NULL || sense_buffer == NULL) {
|
||||
ErrorAlert(STR_NO_MEM_ERR);
|
||||
QuitEmulator();
|
||||
}
|
||||
|
||||
// Create and open IORequests for all 8 units (and all 8 LUNs)
|
||||
for (id=0; id<8; id++) {
|
||||
for (lun=0; lun<8; lun++)
|
||||
ios[id*8+lun] = NULL;
|
||||
char prefs_name[16];
|
||||
sprintf(prefs_name, "scsi%d", id);
|
||||
const char *str = PrefsFindString(prefs_name);
|
||||
if (str) {
|
||||
char dev_name[256];
|
||||
ULONG dev_unit = 0;
|
||||
if (sscanf(str, "%[^/]/%ld", dev_name, &dev_unit) == 2) {
|
||||
for (lun=0; lun<8; lun++) {
|
||||
struct IOStdReq *io = (struct IOStdReq *)CreateIORequest(the_port, sizeof(struct IOStdReq));
|
||||
if (io == NULL)
|
||||
continue;
|
||||
if (OpenDevice((UBYTE *) dev_name, dev_unit + lun * 10, (struct IORequest *)io, 0)) {
|
||||
DeleteIORequest(io);
|
||||
continue;
|
||||
}
|
||||
io->io_Data = &scsi;
|
||||
io->io_Length = sizeof(scsi);
|
||||
io->io_Command = HD_SCSICMD;
|
||||
ios[id*8+lun] = io;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset SCSI bus
|
||||
SCSIReset();
|
||||
|
||||
// Init SCSICmd
|
||||
memset(&scsi, 0, sizeof(scsi));
|
||||
scsi.scsi_Command = cmd_buffer;
|
||||
scsi.scsi_SenseData = sense_buffer;
|
||||
scsi.scsi_SenseLength = SENSE_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void SCSIExit(void)
|
||||
{
|
||||
// Close all devices
|
||||
for (int i=0; i<8; i++)
|
||||
for (int j=0; j<8; j++) {
|
||||
struct IOStdReq *io = ios[i*8+j];
|
||||
if (io) {
|
||||
CloseDevice((struct IORequest *)io);
|
||||
DeleteIORequest(io);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete port and buffers
|
||||
if (the_port)
|
||||
DeleteMsgPort(the_port);
|
||||
if (buffer)
|
||||
FreeMem(buffer, buffer_size);
|
||||
if (sense_buffer)
|
||||
FreeMem(sense_buffer, SENSE_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if requested data size fits into buffer, allocate new buffer if needed
|
||||
*/
|
||||
|
||||
static bool try_buffer(int size)
|
||||
{
|
||||
if (size <= buffer_size)
|
||||
return true;
|
||||
|
||||
UBYTE *new_buffer = (UBYTE *)AllocMem(size, buffer_memf);
|
||||
if (new_buffer == NULL)
|
||||
return false;
|
||||
FreeMem(buffer, buffer_size);
|
||||
buffer = new_buffer;
|
||||
buffer_size = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set SCSI command to be sent by scsi_send_cmd()
|
||||
*/
|
||||
|
||||
void scsi_set_cmd(int cmd_length, uint8 *cmd)
|
||||
{
|
||||
scsi.scsi_CmdLength = cmd_length;
|
||||
memcpy(cmd_buffer, cmd, cmd_length);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for presence of SCSI target
|
||||
*/
|
||||
|
||||
bool scsi_is_target_present(int id)
|
||||
{
|
||||
return ios[id * 8] != NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set SCSI target (returns false on error)
|
||||
*/
|
||||
|
||||
bool scsi_set_target(int id, int lun)
|
||||
{
|
||||
struct IOStdReq *new_io = ios[id * 8 + lun];
|
||||
if (new_io == NULL)
|
||||
return false;
|
||||
if (new_io != io)
|
||||
scsi.scsi_SenseActual = 0; // Clear sense data when selecting new target
|
||||
io = new_io;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send SCSI command to active target (scsi_set_command() must have been called),
|
||||
* read/write data according to S/G table (returns false on error); timeout is in 1/60 sec
|
||||
*/
|
||||
|
||||
bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr, uint32 *sg_len, uint16 *stat, uint32 timeout)
|
||||
{
|
||||
// Bypass the buffer if there's only one S/G table entry
|
||||
bool do_direct_transfer = (sg_size == 1 && ((uint32)sg_ptr[0] & 1) == 0 && direct_transfers_supported);
|
||||
|
||||
if (!do_direct_transfer) {
|
||||
|
||||
// Check if buffer is large enough, allocate new buffer if needed
|
||||
if (!try_buffer(data_length)) {
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_SCSI_BUFFER_ERR), data_length);
|
||||
ErrorAlert(str);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process S/G table when writing
|
||||
if (!reading) {
|
||||
D(bug(" writing to buffer\n"));
|
||||
uint8 *buffer_ptr = buffer;
|
||||
for (int i=0; i<sg_size; i++) {
|
||||
uint32 len = sg_len[i];
|
||||
D(bug(" %d bytes from %08lx\n", len, sg_ptr[i]));
|
||||
memcpy(buffer_ptr, sg_ptr[i], len);
|
||||
buffer_ptr += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request Sense and autosense data valid?
|
||||
BYTE res = 0;
|
||||
if (cmd_buffer[0] == 0x03 && scsi.scsi_SenseActual) {
|
||||
|
||||
// Yes, fake command
|
||||
D(bug(" autosense\n"));
|
||||
memcpy(buffer, sense_buffer, scsi.scsi_SenseActual);
|
||||
scsi.scsi_Status = 0;
|
||||
do_direct_transfer = false;
|
||||
|
||||
} else {
|
||||
|
||||
// No, send regular command
|
||||
D(bug(" sending command, length %ld\n", data_length));
|
||||
if (do_direct_transfer) {
|
||||
scsi.scsi_Data = (UWORD *)sg_ptr[0];
|
||||
scsi.scsi_Length = sg_len[0];
|
||||
} else {
|
||||
scsi.scsi_Data = (UWORD *)buffer;
|
||||
scsi.scsi_Length = data_length;
|
||||
}
|
||||
scsi.scsi_Actual = 0;
|
||||
scsi.scsi_Flags = (reading ? SCSIF_READ : SCSIF_WRITE) | SCSIF_AUTOSENSE;
|
||||
scsi.scsi_SenseActual = 0;
|
||||
scsi.scsi_Status = 0;
|
||||
res = DoIO((struct IORequest *)io);
|
||||
D(bug(" command sent, res %d, status %d\n", res, scsi.scsi_Status));
|
||||
*stat = scsi.scsi_Status;
|
||||
}
|
||||
|
||||
if (!do_direct_transfer) {
|
||||
|
||||
// Process S/G table when reading
|
||||
if (reading && res == 0) {
|
||||
D(bug(" reading from buffer\n"));
|
||||
uint8 *buffer_ptr = buffer;
|
||||
for (int i=0; i<sg_size; i++) {
|
||||
uint32 len = sg_len[i];
|
||||
D(bug(" %d bytes to %08lx\n", len, sg_ptr[i]));
|
||||
memcpy(sg_ptr[i], buffer_ptr, len);
|
||||
buffer_ptr += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res == 0;
|
||||
}
|
|
@ -1,861 +0,0 @@
|
|||
/*
|
||||
* serial_amiga.cpp - Serial device driver, AmigaOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <exec/errors.h>
|
||||
#include <dos/dos.h>
|
||||
#include <dos/dosextens.h>
|
||||
#include <dos/dostags.h>
|
||||
#include <devices/serial.h>
|
||||
#include <devices/parallel.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <inline/exec.h>
|
||||
#include <inline/dos.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "macos_util.h"
|
||||
#include "prefs.h"
|
||||
#include "serial.h"
|
||||
#include "serial_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define MONITOR 0
|
||||
|
||||
|
||||
// These messages are sent to the serial process
|
||||
const uint32 MSG_QUERY = 'qery'; // Query port status, return status in control_io
|
||||
const uint32 MSG_SET_PARAMS = 'setp'; // Set serial parameters (parameters in control_io)
|
||||
const uint32 MSG_SET_PAR_PARAMS = 'pstp'; // Set parallel parameters (parameters in control_io)
|
||||
const uint32 MSG_KILL_IO = 'kill'; // Kill pending I/O requests
|
||||
const uint32 MSG_BREAK = 'brek'; // Send break
|
||||
const uint32 MSG_RESET = 'rset'; // Reset channel
|
||||
const uint32 MSG_PRIME_IN = 'prin'; // Data input
|
||||
const uint32 MSG_PRIME_OUT = 'pout'; // Data output
|
||||
|
||||
struct SerMessage : public Message {
|
||||
SerMessage(uint32 what_, const struct MsgPort *reply_port = NULL)
|
||||
{
|
||||
what = what_;
|
||||
mn_ReplyPort = (struct MsgPort *)reply_port;
|
||||
mn_Length = sizeof(*this);
|
||||
}
|
||||
uint32 what;
|
||||
uint32 pb;
|
||||
};
|
||||
|
||||
|
||||
// Driver private variables
|
||||
class ASERDPort : public SERDPort {
|
||||
public:
|
||||
ASERDPort(const char *dev)
|
||||
{
|
||||
device_name = dev;
|
||||
if (dev && dev[0] == '*') {
|
||||
is_parallel = true;
|
||||
device_name++;
|
||||
} else
|
||||
is_parallel = false;
|
||||
control_io = NULL;
|
||||
serial_proc = NULL;
|
||||
reply_port = NULL;
|
||||
}
|
||||
|
||||
virtual ~ASERDPort()
|
||||
{
|
||||
}
|
||||
|
||||
virtual int16 open(uint16 config);
|
||||
virtual int16 prime_in(uint32 pb, uint32 dce);
|
||||
virtual int16 prime_out(uint32 pb, uint32 dce);
|
||||
virtual int16 control(uint32 pb, uint32 dce, uint16 code);
|
||||
virtual int16 status(uint32 pb, uint32 dce, uint16 code);
|
||||
virtual int16 close(void);
|
||||
|
||||
private:
|
||||
bool configure(uint16 config);
|
||||
void set_handshake(uint32 s, bool with_dtr);
|
||||
void send_to_proc(uint32 what, uint32 pb = 0);
|
||||
bool query(void);
|
||||
bool set_params(void);
|
||||
bool set_par_params(void);
|
||||
void conv_error(struct IOExtSer *io, uint32 dt);
|
||||
static void serial_func(void);
|
||||
|
||||
const char *device_name; // Device name
|
||||
bool is_parallel; // Flag: Port is parallel
|
||||
IOExtSer *control_io; // IORequest for setting serial port characteristics etc.
|
||||
|
||||
struct Process *serial_proc; // Serial device handler process
|
||||
bool proc_error; // Flag: process didn't initialize
|
||||
struct MsgPort *proc_port; // Message port of process, for communication with main task
|
||||
struct MsgPort *reply_port; // Reply port for communication with process
|
||||
|
||||
uint8 err_mask; // shkErrs
|
||||
};
|
||||
|
||||
|
||||
// Global variables
|
||||
static void *proc_arg; // Argument to process
|
||||
extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp)
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void SerialInit(void)
|
||||
{
|
||||
// Read serial preferences and create structs for both ports
|
||||
the_serd_port[0] = new ASERDPort(PrefsFindString("seriala"));
|
||||
the_serd_port[1] = new ASERDPort(PrefsFindString("serialb"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void SerialExit(void)
|
||||
{
|
||||
delete (ASERDPort *)the_serd_port[0];
|
||||
delete (ASERDPort *)the_serd_port[1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open serial port
|
||||
*/
|
||||
|
||||
int16 ASERDPort::open(uint16 config)
|
||||
{
|
||||
// Don't open NULL name devices
|
||||
if (device_name == NULL)
|
||||
return openErr;
|
||||
|
||||
// Init variables
|
||||
err_mask = 0;
|
||||
|
||||
// Create message port
|
||||
reply_port = CreateMsgPort();
|
||||
if (reply_port == NULL)
|
||||
goto open_error;
|
||||
|
||||
// Start process
|
||||
proc_error = false;
|
||||
proc_arg = this;
|
||||
SetSignal(0, SIGF_SINGLE);
|
||||
serial_proc = CreateNewProcTags(
|
||||
NP_Entry, (ULONG)serial_func,
|
||||
NP_Name, (ULONG)"Basilisk II Serial Task",
|
||||
NP_Priority, 1,
|
||||
TAG_END
|
||||
);
|
||||
if (serial_proc == NULL)
|
||||
goto open_error;
|
||||
|
||||
// Wait for signal from process
|
||||
Wait(SIGF_SINGLE);
|
||||
|
||||
// Initialization error? Then bail out
|
||||
if (proc_error)
|
||||
goto open_error;
|
||||
|
||||
// Configure port
|
||||
configure(config);
|
||||
return noErr;
|
||||
|
||||
open_error:
|
||||
serial_proc = NULL;
|
||||
if (reply_port) {
|
||||
DeleteMsgPort(reply_port);
|
||||
reply_port = NULL;
|
||||
}
|
||||
return openErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read data from port
|
||||
*/
|
||||
|
||||
int16 ASERDPort::prime_in(uint32 pb, uint32 dce)
|
||||
{
|
||||
// Send input command to serial process
|
||||
D(bug("primein\n"));
|
||||
read_done = false;
|
||||
read_pending = true;
|
||||
WriteMacInt32(input_dt + serdtDCE, dce);
|
||||
send_to_proc(MSG_PRIME_IN, pb);
|
||||
return 1; // Command in progress
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write data to port
|
||||
*/
|
||||
|
||||
int16 ASERDPort::prime_out(uint32 pb, uint32 dce)
|
||||
{
|
||||
// Send output command to serial process
|
||||
D(bug("primeout\n"));
|
||||
write_done = false;
|
||||
write_pending = true;
|
||||
WriteMacInt32(output_dt + serdtDCE, dce);
|
||||
send_to_proc(MSG_PRIME_OUT, pb);
|
||||
return 1; // Command in progress
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Control calls
|
||||
*/
|
||||
|
||||
int16 ASERDPort::control(uint32 pb, uint32 dce, uint16 code)
|
||||
{
|
||||
D(bug("control(%ld)\n", (uint32)code));
|
||||
switch (code) {
|
||||
case 1: // KillIO
|
||||
send_to_proc(MSG_KILL_IO);
|
||||
return noErr;
|
||||
|
||||
case kSERDConfiguration:
|
||||
if (configure(ReadMacInt16(pb + csParam)))
|
||||
return noErr;
|
||||
else
|
||||
return paramErr;
|
||||
|
||||
case kSERDInputBuffer: {
|
||||
if (is_parallel)
|
||||
return noErr;
|
||||
int buf = ReadMacInt16(pb + csParam + 4) & 0xffffffc0;
|
||||
if (buf < 1024) // 1k minimum
|
||||
buf = 1024;
|
||||
D(bug(" buffer size is now %08lx\n", buf));
|
||||
control_io->io_RBufLen = buf;
|
||||
return set_params() ? noErr : paramErr;
|
||||
}
|
||||
|
||||
case kSERDSerHShake:
|
||||
set_handshake(pb + csParam, false);
|
||||
return noErr;
|
||||
|
||||
case kSERDSetBreak:
|
||||
if (!is_parallel)
|
||||
send_to_proc(MSG_BREAK);
|
||||
return noErr;
|
||||
|
||||
case kSERDClearBreak:
|
||||
return noErr;
|
||||
|
||||
case kSERDBaudRate:
|
||||
if (is_parallel)
|
||||
return noErr;
|
||||
control_io->io_Baud = ReadMacInt16(pb + csParam);
|
||||
D(bug(" baud rate %ld\n", control_io->io_Baud));
|
||||
return set_params() ? noErr : paramErr;
|
||||
|
||||
case kSERDHandshake:
|
||||
case kSERDHandshakeRS232:
|
||||
set_handshake(pb + csParam, true);
|
||||
return noErr;
|
||||
|
||||
case kSERDClockMIDI:
|
||||
if (is_parallel)
|
||||
return noErr;
|
||||
control_io->io_Baud = 31250;
|
||||
control_io->io_SerFlags = SERF_XDISABLED | SERF_SHARED;
|
||||
control_io->io_StopBits = 1;
|
||||
control_io->io_ReadLen = control_io->io_WriteLen = 8;
|
||||
return set_params() ? noErr : paramErr;
|
||||
|
||||
case kSERDMiscOptions:
|
||||
case kSERDAssertDTR:
|
||||
case kSERDNegateDTR:
|
||||
case kSERDSetPEChar:
|
||||
case kSERDSetPEAltChar:
|
||||
case kSERDAssertRTS:
|
||||
case kSERDNegateRTS:
|
||||
return noErr; // Not supported under AmigaOS
|
||||
|
||||
case kSERD115KBaud:
|
||||
if (is_parallel)
|
||||
return noErr;
|
||||
control_io->io_Baud = 115200;
|
||||
return set_params() ? noErr : paramErr;
|
||||
|
||||
case kSERD230KBaud:
|
||||
case kSERDSetHighSpeed:
|
||||
if (is_parallel)
|
||||
return noErr;
|
||||
control_io->io_Baud = 230400;
|
||||
return set_params() ? noErr : paramErr;
|
||||
|
||||
case kSERDResetChannel:
|
||||
send_to_proc(MSG_RESET);
|
||||
return noErr;
|
||||
|
||||
default:
|
||||
printf("WARNING: SerialControl(): unimplemented control code %d\n", code);
|
||||
return controlErr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Status calls
|
||||
*/
|
||||
|
||||
int16 ASERDPort::status(uint32 pb, uint32 dce, uint16 code)
|
||||
{
|
||||
D(bug("status(%ld)\n", (uint32)code));
|
||||
switch (code) {
|
||||
case kSERDInputCount:
|
||||
WriteMacInt32(pb + csParam, 0);
|
||||
if (!is_parallel) {
|
||||
if (!query())
|
||||
return noErr;
|
||||
D(bug("status(2) successful, returning %08lx\n", control_io->IOSer.io_Actual));
|
||||
WriteMacInt32(pb + csParam, control_io->IOSer.io_Actual);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERDStatus: {
|
||||
uint32 p = pb + csParam;
|
||||
WriteMacInt8(p + staCumErrs, cum_errors);
|
||||
cum_errors = 0;
|
||||
WriteMacInt8(p + staRdPend, read_pending);
|
||||
WriteMacInt8(p + staWrPend, write_pending);
|
||||
if (is_parallel) {
|
||||
WriteMacInt8(p + staXOffSent, 0);
|
||||
WriteMacInt8(p + staXOffHold, 0);
|
||||
WriteMacInt8(p + staCtsHold, 0);
|
||||
WriteMacInt8(p + staDsrHold, 0);
|
||||
WriteMacInt8(p + staModemStatus, dsrEvent | dcdEvent | ctsEvent);
|
||||
} else {
|
||||
query();
|
||||
WriteMacInt8(p + staXOffSent,
|
||||
(control_io->io_Status & IO_STATF_XOFFREAD ? xOffWasSent : 0)
|
||||
| (control_io->io_Status & (1 << 6) ? dtrNegated : 0)); // RTS
|
||||
WriteMacInt8(p + staXOffHold, control_io->io_Status & IO_STATF_XOFFWRITE);
|
||||
WriteMacInt8(p + staCtsHold, control_io->io_Status & (1 << 4)); // CTS
|
||||
WriteMacInt8(p + staDsrHold, control_io->io_Status & (1 << 3)); // DSR
|
||||
WriteMacInt8(p + staModemStatus,
|
||||
(control_io->io_Status & (1 << 3) ? 0 : dsrEvent)
|
||||
| (control_io->io_Status & (1 << 2) ? riEvent : 0)
|
||||
| (control_io->io_Status & (1 << 5) ? 0 : dcdEvent)
|
||||
| (control_io->io_Status & (1 << 4) ? 0 : ctsEvent)
|
||||
| (control_io->io_Status & IO_STATF_READBREAK ? breakEvent : 0));
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("WARNING: SerialStatus(): unimplemented status code %d\n", code);
|
||||
return statusErr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close serial port
|
||||
*/
|
||||
|
||||
int16 ASERDPort::close()
|
||||
{
|
||||
// Stop process
|
||||
if (serial_proc) {
|
||||
SetSignal(0, SIGF_SINGLE);
|
||||
Signal(&serial_proc->pr_Task, SIGBREAKF_CTRL_C);
|
||||
Wait(SIGF_SINGLE);
|
||||
}
|
||||
|
||||
// Delete reply port
|
||||
if (reply_port) {
|
||||
DeleteMsgPort(reply_port);
|
||||
reply_port = NULL;
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Configure serial port with MacOS config word
|
||||
*/
|
||||
|
||||
bool ASERDPort::configure(uint16 config)
|
||||
{
|
||||
D(bug(" configure %04lx\n", (uint32)config));
|
||||
if (is_parallel)
|
||||
return true;
|
||||
|
||||
// Set number of stop bits
|
||||
switch (config & 0xc000) {
|
||||
case stop10:
|
||||
control_io->io_StopBits = 1;
|
||||
break;
|
||||
case stop20:
|
||||
control_io->io_StopBits = 2;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set parity mode
|
||||
switch (config & 0x3000) {
|
||||
case noParity:
|
||||
control_io->io_SerFlags &= ~SERF_PARTY_ON;
|
||||
break;
|
||||
case oddParity:
|
||||
control_io->io_SerFlags |= SERF_PARTY_ON | SERF_PARTY_ODD;
|
||||
break;
|
||||
case evenParity:
|
||||
control_io->io_SerFlags |= SERF_PARTY_ON;
|
||||
control_io->io_SerFlags &= ~SERF_PARTY_ODD;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set number of data bits
|
||||
switch (config & 0x0c00) {
|
||||
case data5:
|
||||
control_io->io_ReadLen = control_io->io_WriteLen = 5;
|
||||
break;
|
||||
case data6:
|
||||
control_io->io_ReadLen = control_io->io_WriteLen = 6;
|
||||
break;
|
||||
case data7:
|
||||
control_io->io_ReadLen = control_io->io_WriteLen = 7;
|
||||
break;
|
||||
case data8:
|
||||
control_io->io_ReadLen = control_io->io_WriteLen = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set baud rate
|
||||
control_io->io_Baud = 115200 / ((config & 0x03ff) + 2);
|
||||
return set_params();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set serial handshaking
|
||||
*/
|
||||
|
||||
void ASERDPort::set_handshake(uint32 s, bool with_dtr)
|
||||
{
|
||||
D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3),
|
||||
ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7)));
|
||||
|
||||
err_mask = ReadMacInt8(s + shkErrs);
|
||||
|
||||
if (is_parallel) {
|
||||
|
||||
// Parallel handshake
|
||||
if (with_dtr) {
|
||||
if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR))
|
||||
((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE;
|
||||
else
|
||||
((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE;
|
||||
} else {
|
||||
if (ReadMacInt8(s + shkFCTS))
|
||||
((IOExtPar *)control_io)->io_ParFlags |= PARF_ACKMODE;
|
||||
else
|
||||
((IOExtPar *)control_io)->io_ParFlags &= ~PARF_ACKMODE;
|
||||
}
|
||||
set_par_params();
|
||||
|
||||
} else {
|
||||
|
||||
// Serial handshake
|
||||
if (ReadMacInt8(s + shkFXOn) || ReadMacInt8(s + shkFInX))
|
||||
control_io->io_SerFlags &= ~SERF_XDISABLED;
|
||||
else
|
||||
control_io->io_SerFlags |= SERF_XDISABLED;
|
||||
|
||||
if (with_dtr) {
|
||||
if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR))
|
||||
control_io->io_SerFlags |= SERF_7WIRE;
|
||||
else
|
||||
control_io->io_SerFlags &= ~SERF_7WIRE;
|
||||
} else {
|
||||
if (ReadMacInt8(s + shkFCTS))
|
||||
control_io->io_SerFlags |= SERF_7WIRE;
|
||||
else
|
||||
control_io->io_SerFlags &= ~SERF_7WIRE;
|
||||
}
|
||||
control_io->io_CtlChar = ReadMacInt16(s + shkXOn) << 16;
|
||||
set_params();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send message to serial process
|
||||
*/
|
||||
|
||||
void ASERDPort::send_to_proc(uint32 what, uint32 pb)
|
||||
{
|
||||
D(bug("sending %08lx to serial_proc\n", what));
|
||||
SerMessage msg(what, reply_port);
|
||||
msg.pb = pb;
|
||||
PutMsg(proc_port, &msg);
|
||||
WaitPort(reply_port);
|
||||
GetMsg(reply_port);
|
||||
D(bug(" sent\n"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Query serial port status
|
||||
*/
|
||||
|
||||
bool ASERDPort::query(void)
|
||||
{
|
||||
send_to_proc(MSG_QUERY);
|
||||
return control_io->IOSer.io_Error == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set serial parameters
|
||||
*/
|
||||
|
||||
bool ASERDPort::set_params(void)
|
||||
{
|
||||
// Set/clear RadBoogie
|
||||
UBYTE flags = control_io->io_SerFlags;
|
||||
if (!(flags & SERF_PARTY_ON) && (flags & SERF_XDISABLED) && control_io->io_ReadLen == 8)
|
||||
control_io->io_SerFlags |= SERF_RAD_BOOGIE;
|
||||
else
|
||||
control_io->io_SerFlags &= ~SERF_RAD_BOOGIE;
|
||||
|
||||
// Send message to serial process
|
||||
send_to_proc(MSG_SET_PARAMS);
|
||||
return control_io->IOSer.io_Error == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set parallel parameters
|
||||
*/
|
||||
|
||||
bool ASERDPort::set_par_params(void)
|
||||
{
|
||||
send_to_proc(MSG_SET_PAR_PARAMS);
|
||||
return control_io->IOSer.io_Error == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert AmigaOS error code to MacOS error code, set serdtResult and cum_errors
|
||||
*/
|
||||
|
||||
void ASERDPort::conv_error(struct IOExtSer *io, uint32 dt)
|
||||
{
|
||||
int16 oserr;
|
||||
uint8 cum;
|
||||
|
||||
BYTE err = io->IOSer.io_Error;
|
||||
if (err == 0 || err == IOERR_NOCMD) {
|
||||
oserr = 0;
|
||||
cum = 0;
|
||||
} else {
|
||||
if (is_parallel) {
|
||||
oserr = (err_mask & framingErr) ? rcvrErr : 0;
|
||||
cum = framingErr;
|
||||
} else {
|
||||
switch (io->IOSer.io_Error) {
|
||||
case SerErr_DetectedBreak:
|
||||
oserr = breakRecd;
|
||||
cum = breakErr;
|
||||
break;
|
||||
case SerErr_ParityErr:
|
||||
oserr = (err_mask & parityErr) ? rcvrErr : 0;
|
||||
cum = parityErr;
|
||||
break;
|
||||
case SerErr_BufOverflow:
|
||||
oserr = (err_mask & swOverrunErr) ? rcvrErr : 0;
|
||||
cum = swOverrunErr;
|
||||
break;
|
||||
case SerErr_LineErr:
|
||||
oserr = (err_mask & hwOverrunErr) ? rcvrErr : 0;
|
||||
cum = hwOverrunErr;
|
||||
break;
|
||||
default:
|
||||
oserr = (err_mask & framingErr) ? rcvrErr : 0;
|
||||
cum = framingErr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WriteMacInt32(dt + serdtResult, oserr);
|
||||
cum_errors |= cum;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process for communication with the serial.device
|
||||
*/
|
||||
|
||||
__saveds void ASERDPort::serial_func(void)
|
||||
{
|
||||
struct ASERDPort *obj = (ASERDPort *)proc_arg;
|
||||
struct MsgPort *proc_port = NULL, *io_port = NULL, *control_port = NULL;
|
||||
struct IOExtSer *read_io = NULL, *write_io = NULL, *control_io = NULL;
|
||||
uint8 orig_params[sizeof(struct IOExtSer)];
|
||||
bool opened = false;
|
||||
ULONG io_mask = 0, proc_port_mask = 0;
|
||||
|
||||
// Default: error occured
|
||||
obj->proc_error = true;
|
||||
|
||||
// Create message port for communication with main task
|
||||
proc_port = CreateMsgPort();
|
||||
if (proc_port == NULL)
|
||||
goto quit;
|
||||
proc_port_mask = 1 << proc_port->mp_SigBit;
|
||||
|
||||
// Create message ports for serial.device I/O
|
||||
io_port = CreateMsgPort();
|
||||
if (io_port == NULL)
|
||||
goto quit;
|
||||
io_mask = 1 << io_port->mp_SigBit;
|
||||
control_port = CreateMsgPort();
|
||||
if (control_port == NULL)
|
||||
goto quit;
|
||||
|
||||
// Create IORequests
|
||||
read_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
|
||||
write_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer));
|
||||
control_io = (struct IOExtSer *)CreateIORequest(control_port, sizeof(struct IOExtSer));
|
||||
if (read_io == NULL || write_io == NULL || control_io == NULL)
|
||||
goto quit;
|
||||
read_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug
|
||||
write_io->IOSer.io_Message.mn_Node.ln_Type = 0;
|
||||
control_io->IOSer.io_Message.mn_Node.ln_Type = 0;
|
||||
|
||||
// Parse device name
|
||||
char dev_name[256];
|
||||
ULONG dev_unit;
|
||||
if (sscanf(obj->device_name, "%[^/]/%ld", dev_name, &dev_unit) < 2)
|
||||
goto quit;
|
||||
|
||||
// Open device
|
||||
if (obj->is_parallel)
|
||||
((IOExtPar *)read_io)->io_ParFlags = PARF_SHARED;
|
||||
else
|
||||
read_io->io_SerFlags = SERF_SHARED | SERF_7WIRE;
|
||||
if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)read_io, 0) || read_io->IOSer.io_Device == NULL)
|
||||
goto quit;
|
||||
opened = true;
|
||||
|
||||
// Copy IORequests
|
||||
memcpy(write_io, read_io, sizeof(struct IOExtSer));
|
||||
memcpy(control_io, read_io, sizeof(struct IOExtSer));
|
||||
|
||||
// Attach control_io to control_port and set default values
|
||||
control_io->IOSer.io_Message.mn_ReplyPort = control_port;
|
||||
if (!obj->is_parallel) {
|
||||
control_io->io_CtlChar = SER_DEFAULT_CTLCHAR;
|
||||
control_io->io_RBufLen = 64;
|
||||
control_io->io_ExtFlags = 0;
|
||||
control_io->io_Baud = 9600;
|
||||
control_io->io_BrkTime = 250000;
|
||||
control_io->io_ReadLen = control_io->io_WriteLen = 8;
|
||||
control_io->io_StopBits = 1;
|
||||
control_io->io_SerFlags = SERF_SHARED;
|
||||
control_io->IOSer.io_Command = SDCMD_SETPARAMS;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
|
||||
}
|
||||
|
||||
// Initialization went well, inform main task
|
||||
obj->proc_port = proc_port;
|
||||
obj->control_io = control_io;
|
||||
obj->proc_error = false;
|
||||
Signal(MainTask, SIGF_SINGLE);
|
||||
|
||||
// Main loop
|
||||
for (;;) {
|
||||
|
||||
// Wait for I/O and messages (CTRL_C is used for quitting the task)
|
||||
ULONG sig = Wait(proc_port_mask | io_mask | SIGBREAKF_CTRL_C);
|
||||
|
||||
// Main task wants to quit us
|
||||
if (sig & SIGBREAKF_CTRL_C)
|
||||
break;
|
||||
|
||||
// Main task sent a command to us
|
||||
if (sig & proc_port_mask) {
|
||||
struct SerMessage *msg;
|
||||
while (msg = (SerMessage *)GetMsg(proc_port)) {
|
||||
D(bug("serial_proc received %08lx\n", msg->what));
|
||||
switch (msg->what) {
|
||||
case MSG_QUERY:
|
||||
control_io->IOSer.io_Command = SDCMD_QUERY;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
D(bug(" query returned %08lx, actual %08lx\n", control_io->IOSer.io_Error, control_io->IOSer.io_Actual));
|
||||
break;
|
||||
|
||||
case MSG_SET_PARAMS:
|
||||
// Only send SDCMD_SETPARAMS when configuration has changed
|
||||
if (memcmp(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar))) {
|
||||
memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
|
||||
memcpy(&(read_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
|
||||
memcpy(&(write_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar));
|
||||
control_io->IOSer.io_Command = SDCMD_SETPARAMS;
|
||||
D(bug(" params %08lx %08lx %08lx %08lx %08lx %08lx\n", control_io->io_CtlChar, control_io->io_RBufLen, control_io->io_ExtFlags, control_io->io_Baud, control_io->io_BrkTime, *(uint32 *)((uint8 *)control_io + 76)));
|
||||
DoIO((struct IORequest *)control_io);
|
||||
D(bug(" set_parms returned %08lx\n", control_io->IOSer.io_Error));
|
||||
}
|
||||
break;
|
||||
|
||||
case MSG_SET_PAR_PARAMS:
|
||||
control_io->IOSer.io_Command = PDCMD_SETPARAMS;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
D(bug(" set_par_parms returned %08lx\n", control_io->IOSer.io_Error));
|
||||
break;
|
||||
|
||||
case MSG_BREAK:
|
||||
control_io->IOSer.io_Command = SDCMD_BREAK;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
D(bug(" break returned %08lx\n", control_io->IOSer.io_Error));
|
||||
break;
|
||||
|
||||
case MSG_RESET:
|
||||
control_io->IOSer.io_Command = CMD_RESET;
|
||||
DoIO((struct IORequest *)control_io);
|
||||
D(bug(" reset returned %08lx\n", control_io->IOSer.io_Error));
|
||||
break;
|
||||
|
||||
case MSG_KILL_IO:
|
||||
AbortIO((struct IORequest *)read_io);
|
||||
AbortIO((struct IORequest *)write_io);
|
||||
WaitIO((struct IORequest *)read_io);
|
||||
WaitIO((struct IORequest *)write_io);
|
||||
obj->read_pending = obj->write_pending = false;
|
||||
obj->read_done = obj->write_done = false;
|
||||
break;
|
||||
|
||||
case MSG_PRIME_IN:
|
||||
read_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
|
||||
read_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
|
||||
read_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
|
||||
read_io->IOSer.io_Actual = 0;
|
||||
read_io->IOSer.io_Command = CMD_READ;
|
||||
D(bug("serial_proc receiving %ld bytes from %08lx\n", read_io->IOSer.io_Length, read_io->IOSer.io_Data));
|
||||
SendIO((struct IORequest *)read_io);
|
||||
break;
|
||||
|
||||
case MSG_PRIME_OUT: {
|
||||
write_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb;
|
||||
write_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
|
||||
write_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount);
|
||||
write_io->IOSer.io_Actual = 0;
|
||||
write_io->IOSer.io_Command = CMD_WRITE;
|
||||
D(bug("serial_proc transmitting %ld bytes from %08lx\n", write_io->IOSer.io_Length, write_io->IOSer.io_Data));
|
||||
#if MONITOR
|
||||
bug("Sending serial data:\n");
|
||||
uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
|
||||
for (int i=0; i<len; i++) {
|
||||
bug("%02lx ", adr[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
SendIO((struct IORequest *)write_io);
|
||||
break;
|
||||
}
|
||||
}
|
||||
D(bug(" serial_proc replying\n"));
|
||||
ReplyMsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// I/O operation completed
|
||||
if (sig & io_mask) {
|
||||
struct IOExtSer *io;
|
||||
while (io = (struct IOExtSer *)GetMsg(io_port)) {
|
||||
if (io == read_io) {
|
||||
D(bug("read_io complete, %ld bytes received, error %ld\n", read_io->IOSer.io_Actual, read_io->IOSer.io_Error));
|
||||
uint32 pb = (uint32)read_io->IOSer.io_Message.mn_Node.ln_Name;
|
||||
#if MONITOR
|
||||
bug("Receiving serial data:\n");
|
||||
uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer));
|
||||
for (int i=0; i<read_io->IOSer.io_Actual; i++) {
|
||||
bug("%02lx ", adr[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
WriteMacInt32(pb + ioActCount, read_io->IOSer.io_Actual);
|
||||
obj->conv_error(read_io, obj->input_dt);
|
||||
obj->read_done = true;
|
||||
SetInterruptFlag(INTFLAG_SERIAL);
|
||||
TriggerInterrupt();
|
||||
} else if (io == write_io) {
|
||||
D(bug("write_io complete, %ld bytes sent, error %ld\n", write_io->IOSer.io_Actual, write_io->IOSer.io_Error));
|
||||
uint32 pb = (uint32)write_io->IOSer.io_Message.mn_Node.ln_Name;
|
||||
WriteMacInt32(pb + ioActCount, write_io->IOSer.io_Actual);
|
||||
obj->conv_error(write_io, obj->output_dt);
|
||||
obj->write_done = true;
|
||||
SetInterruptFlag(INTFLAG_SERIAL);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
quit:
|
||||
|
||||
// Close everything
|
||||
if (opened) {
|
||||
if (CheckIO((struct IORequest *)write_io) == 0) {
|
||||
AbortIO((struct IORequest *)write_io);
|
||||
WaitIO((struct IORequest *)write_io);
|
||||
}
|
||||
if (CheckIO((struct IORequest *)read_io) == 0) {
|
||||
AbortIO((struct IORequest *)read_io);
|
||||
WaitIO((struct IORequest *)read_io);
|
||||
}
|
||||
CloseDevice((struct IORequest *)read_io);
|
||||
}
|
||||
if (control_io)
|
||||
DeleteIORequest(control_io);
|
||||
if (write_io)
|
||||
DeleteIORequest(write_io);
|
||||
if (read_io)
|
||||
DeleteIORequest(read_io);
|
||||
if (control_port)
|
||||
DeleteMsgPort(control_port);
|
||||
if (io_port)
|
||||
DeleteMsgPort(io_port);
|
||||
|
||||
// Send signal to main task to confirm termination
|
||||
Forbid();
|
||||
Signal(MainTask, SIGF_SINGLE);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* sysdeps.h - System dependent definitions for AmigaOS
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SYSDEPS_H
|
||||
#define SYSDEPS_H
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <devices/timer.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "user_strings_amiga.h"
|
||||
|
||||
// Mac and host address space are the same
|
||||
#define REAL_ADDRESSING 1
|
||||
|
||||
// Using 68k natively
|
||||
#define EMULATED_68K 0
|
||||
|
||||
// Mac ROM is not write protected
|
||||
#define ROM_IS_WRITE_PROTECTED 0
|
||||
#define USE_SCRATCHMEM_SUBTERFUGE 1
|
||||
|
||||
// ExtFS is supported
|
||||
#define SUPPORTS_EXTFS 1
|
||||
|
||||
// mon is not supported
|
||||
#undef ENABLE_MON
|
||||
|
||||
// Data types
|
||||
typedef unsigned char uint8;
|
||||
typedef signed char int8;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed short int16;
|
||||
typedef unsigned long uint32;
|
||||
typedef signed long int32;
|
||||
typedef unsigned long long uint64;
|
||||
typedef signed long long int64;
|
||||
|
||||
typedef unsigned long long loff_t;
|
||||
|
||||
// Time data type for Time Manager emulation
|
||||
typedef struct timeval tm_time_t;
|
||||
|
||||
// Endianess conversion (not needed)
|
||||
#define ntohs(x) (x)
|
||||
#define ntohl(x) (x)
|
||||
#define htons(x) (x)
|
||||
#define htonl(x) (x)
|
||||
|
||||
// Some systems don't define this (ExecBase->AttnFlags)
|
||||
#ifndef AFF_68060
|
||||
#define AFF_68060 (1L<<7)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* timer_amiga.cpp - Time Manager emulation, AmigaOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <exec/types.h>
|
||||
#include <devices/timer.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/timer.h>
|
||||
#include <proto/intuition.h>
|
||||
#include <inline/timer.h>
|
||||
#include <inline/intuition.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
/*
|
||||
* Return microseconds since boot (64 bit)
|
||||
*/
|
||||
|
||||
void Microseconds(uint32 &hi, uint32 &lo)
|
||||
{
|
||||
D(bug("Microseconds\n"));
|
||||
struct timeval tv;
|
||||
GetSysTime(&tv);
|
||||
uint64 tl = (uint64)tv.tv_secs * 1000000 + tv.tv_micro;
|
||||
hi = tl >> 32;
|
||||
lo = tl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return local date/time in Mac format (seconds since 1.1.1904)
|
||||
*/
|
||||
|
||||
uint32 TimerDateTime(void)
|
||||
{
|
||||
ULONG secs, mics;
|
||||
CurrentTime(&secs, &mics);
|
||||
return secs + 0x8b31ef80;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get current time
|
||||
*/
|
||||
|
||||
void timer_current_time(tm_time_t &t)
|
||||
{
|
||||
GetSysTime(&t);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add times
|
||||
*/
|
||||
|
||||
void timer_add_time(tm_time_t &res, tm_time_t a, tm_time_t b)
|
||||
{
|
||||
res = a;
|
||||
AddTime(&res, &b);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Subtract times
|
||||
*/
|
||||
|
||||
void timer_sub_time(tm_time_t &res, tm_time_t a, tm_time_t b)
|
||||
{
|
||||
res = a;
|
||||
SubTime(&res, &b);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compare times (<0: a < b, =0: a = b, >0: a > b)
|
||||
*/
|
||||
|
||||
int timer_cmp_time(tm_time_t a, tm_time_t b)
|
||||
{
|
||||
return CmpTime(&b, &a);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert Mac time value (>0: microseconds, <0: microseconds) to tm_time_t
|
||||
*/
|
||||
|
||||
void timer_mac2host_time(tm_time_t &res, int32 mactime)
|
||||
{
|
||||
if (mactime > 0) {
|
||||
res.tv_secs = mactime / 1000; // Time in milliseconds
|
||||
res.tv_micro = (mactime % 1000) * 1000;
|
||||
} else {
|
||||
res.tv_secs = -mactime / 1000000; // Time in negative microseconds
|
||||
res.tv_micro = -mactime % 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert positive tm_time_t to Mac time value (>0: microseconds, <0: microseconds)
|
||||
* A negative input value for hosttime results in a zero return value
|
||||
* As long as the microseconds value fits in 32 bit, it must not be converted to milliseconds!
|
||||
*/
|
||||
|
||||
int32 timer_host2mac_time(tm_time_t hosttime)
|
||||
{
|
||||
if (hosttime.tv_secs < 0)
|
||||
return 0;
|
||||
else {
|
||||
uint64 t = (uint64)hosttime.tv_secs * 1000000 + hosttime.tv_micro;
|
||||
if (t > 0x7fffffff)
|
||||
return t / 1000; // Time in milliseconds
|
||||
else
|
||||
return -t; // Time in negative microseconds
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Suspend emulator thread, virtual CPU in idle mode
|
||||
*/
|
||||
|
||||
void idle_wait(void)
|
||||
{
|
||||
// XXX if you implement this make sure to call idle_resume() from TriggerInterrupt()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resume execution of emulator thread, events just arrived
|
||||
*/
|
||||
|
||||
void idle_resume(void)
|
||||
{
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* user_strings_amiga.cpp - AmigaOS-specific localizable strings
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "user_strings.h"
|
||||
|
||||
|
||||
// Platform-specific string definitions
|
||||
user_string_def platform_strings[] = {
|
||||
// Common strings that have a platform-specific variant
|
||||
{STR_VOLUME_IS_MOUNTED_WARN, "The volume '%s' is mounted under AmigaOS. Basilisk II will try to unmount it."},
|
||||
{STR_EXTFS_CTRL, "Amiga Root"},
|
||||
{STR_EXTFS_NAME, "Amiga Directory Tree"},
|
||||
{STR_EXTFS_VOLUME_NAME, "Amiga"},
|
||||
|
||||
// Purely platform-specific strings
|
||||
{STR_NO_PREPARE_EMUL_ERR, "PrepareEmul is not installed. Run PrepareEmul and then try again to start Basilisk II."},
|
||||
{STR_NO_GADTOOLS_LIB_ERR, "Cannot open gadtools.library V39."},
|
||||
{STR_NO_IFFPARSE_LIB_ERR, "Cannot open iffparse.library V39."},
|
||||
{STR_NO_ASL_LIB_ERR, "Cannot open asl.library V36."},
|
||||
{STR_NO_TIMER_DEV_ERR, "Cannot open timer.device."},
|
||||
{STR_NO_P96_MODE_ERR, "The selected screen mode is not a Picasso96 or CyberGraphX mode."},
|
||||
{STR_NO_VIDEO_MODE_ERR, "Cannot obtain selected video mode."},
|
||||
{STR_WRONG_SCREEN_DEPTH_ERR, "Basilisk II only supports 8, 16 or 24 bit screens."},
|
||||
{STR_WRONG_SCREEN_FORMAT_ERR, "Basilisk II only supports big-endian chunky ARGB screen modes."},
|
||||
{STR_ENFORCER_RUNNING_ERR, "Enforcer/CyberGuard is running. Remove and then try again to start Basilisk II."},
|
||||
|
||||
{STR_NOT_ETHERNET_WARN, "The selected network device is not an Ethernet device. Networking will be disabled."},
|
||||
{STR_NO_MULTICAST_WARN, "Your Ethernet card does not support multicast and is not usable with AppleTalk. Please report this to the manufacturer of the card."},
|
||||
{STR_NO_GTLAYOUT_LIB_WARN, "Cannot open gtlayout.library V39. The preferences editor GUI will not be available."},
|
||||
{STR_NO_AHI_WARN, "Cannot open ahi.device V2. Audio output will be disabled."},
|
||||
{STR_NO_AHI_CTRL_WARN, "Cannot open AHI control structure. Audio output will be disabled."},
|
||||
{STR_NOT_ENOUGH_MEM_WARN, "Could not get %lu MBytes of memory.\nShould I use the largest Block (%lu MBytes) instead ?"},
|
||||
|
||||
{STR_AHI_MODE_CTRL, "AHI Mode"},
|
||||
{STR_SCSI_MEMTYPE_CTRL, "Buffer Memory Type"},
|
||||
{STR_MEMTYPE_CHIP_LAB, "Chip"},
|
||||
{STR_MEMTYPE_24BITDMA_LAB, "24-Bit DMA"},
|
||||
{STR_MEMTYPE_ANY_LAB, "Any"},
|
||||
{STR_SCSI_DEVICES_CTRL, "Virtual SCSI Devices"},
|
||||
|
||||
{-1, NULL} // End marker
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Fetch pointer to string, given the string number
|
||||
*/
|
||||
|
||||
const char *GetString(int num)
|
||||
{
|
||||
// First search for platform-specific string
|
||||
int i = 0;
|
||||
while (platform_strings[i].num >= 0) {
|
||||
if (platform_strings[i].num == num)
|
||||
return platform_strings[i].str;
|
||||
i++;
|
||||
}
|
||||
|
||||
// Not found, search for common string
|
||||
i = 0;
|
||||
while (common_strings[i].num >= 0) {
|
||||
if (common_strings[i].num == num)
|
||||
return common_strings[i].str;
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* user_strings_amiga.h - AmigaOS-specific localizable strings
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef USER_STRINGS_AMIGA_H
|
||||
#define USER_STRINGS_AMIGA_H
|
||||
|
||||
enum {
|
||||
STR_NO_PREPARE_EMUL_ERR = 10000,
|
||||
STR_NO_GADTOOLS_LIB_ERR,
|
||||
STR_NO_IFFPARSE_LIB_ERR,
|
||||
STR_NO_ASL_LIB_ERR,
|
||||
STR_NO_TIMER_DEV_ERR,
|
||||
STR_NO_P96_MODE_ERR,
|
||||
STR_NO_VIDEO_MODE_ERR,
|
||||
STR_WRONG_SCREEN_DEPTH_ERR,
|
||||
STR_WRONG_SCREEN_FORMAT_ERR,
|
||||
STR_ENFORCER_RUNNING_ERR,
|
||||
|
||||
STR_NOT_ETHERNET_WARN,
|
||||
STR_NO_MULTICAST_WARN,
|
||||
STR_NO_GTLAYOUT_LIB_WARN,
|
||||
STR_NO_AHI_WARN,
|
||||
STR_NO_AHI_CTRL_WARN,
|
||||
STR_NOT_ENOUGH_MEM_WARN,
|
||||
|
||||
STR_AHI_MODE_CTRL,
|
||||
STR_SCSI_MEMTYPE_CTRL,
|
||||
STR_MEMTYPE_CHIP_LAB,
|
||||
STR_MEMTYPE_24BITDMA_LAB,
|
||||
STR_MEMTYPE_ANY_LAB,
|
||||
STR_SCSI_DEVICES_CTRL
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* xpram_amiga.cpp - XPRAM handling, AmigaOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <exec/types.h>
|
||||
#define __USE_SYSBASE
|
||||
#include <proto/dos.h>
|
||||
#include <inline/dos.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "xpram.h"
|
||||
|
||||
|
||||
// XPRAM file name
|
||||
#if POWERPC_ROM
|
||||
static char XPRAM_FILE_NAME[] = "ENV:SheepShaver_NVRAM";
|
||||
static char XPRAM_FILE_NAME_ARC[] = "ENVARC:SheepShaver_NVRAM";
|
||||
#else
|
||||
static char XPRAM_FILE_NAME[] = "ENV:BasiliskII_XPRAM";
|
||||
static char XPRAM_FILE_NAME_ARC[] = "ENVARC:BasiliskII_XPRAM";
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Load XPRAM from settings file
|
||||
*/
|
||||
|
||||
void LoadXPRAM(void)
|
||||
{
|
||||
BPTR fh;
|
||||
if ((fh = Open(XPRAM_FILE_NAME, MODE_OLDFILE)) != NULL) {
|
||||
Read(fh, XPRAM, XPRAM_SIZE);
|
||||
Close(fh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save XPRAM to settings file
|
||||
*/
|
||||
|
||||
void SaveXPRAM(void)
|
||||
{
|
||||
BPTR fh;
|
||||
if ((fh = Open(XPRAM_FILE_NAME, MODE_NEWFILE)) != NULL) {
|
||||
Write(fh, XPRAM, XPRAM_SIZE);
|
||||
Close(fh);
|
||||
}
|
||||
if ((fh = Open(XPRAM_FILE_NAME_ARC, MODE_NEWFILE)) != NULL) {
|
||||
Write(fh, XPRAM, XPRAM_SIZE);
|
||||
Close(fh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete PRAM file
|
||||
*/
|
||||
|
||||
void ZapPRAM(void)
|
||||
{
|
||||
DeleteFile(XPRAM_FILE_NAME);
|
||||
DeleteFile(XPRAM_FILE_NAME_ARC);
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
## BeOS Generic Makefile v2.1 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME= BasiliskII
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE= APP
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
MACHINE=$(shell uname -m)
|
||||
ifeq ($(MACHINE), BePC)
|
||||
CPUSRCS = ../uae_cpu/basilisk_glue.cpp ../uae_cpu/memory.cpp ../uae_cpu/newcpu.cpp \
|
||||
../uae_cpu/readcpu.cpp ../uae_cpu/fpu/fpu_x86.cpp cpustbl.cpp cpudefs.cpp cpufast.s
|
||||
else
|
||||
# CPUSRCS = ../powerrom_cpu/powerrom_cpu.cpp
|
||||
CPUSRCS = ../uae_cpu/basilisk_glue.cpp ../uae_cpu/newcpu.cpp \
|
||||
../uae_cpu/readcpu.cpp ../uae_cpu/fpu/fpu_uae.cpp cpustbl.cpp cpudefs.cpp cpuemu.cpp
|
||||
endif
|
||||
SRCS = ../main.cpp main_beos.cpp ../prefs.cpp ../prefs_items.cpp prefs_beos.cpp \
|
||||
prefs_editor_beos.cpp sys_beos.cpp ../rom_patches.cpp ../slot_rom.cpp \
|
||||
../rsrc_patches.cpp ../emul_op.cpp ../macos_util.cpp ../xpram.cpp \
|
||||
xpram_beos.cpp ../timer.cpp timer_beos.cpp clip_beos.cpp ../adb.cpp \
|
||||
../serial.cpp serial_beos.cpp ../ether.cpp ether_beos.cpp ../sony.cpp \
|
||||
../disk.cpp ../cdrom.cpp ../scsi.cpp scsi_beos.cpp ../video.cpp \
|
||||
video_beos.cpp ../audio.cpp audio_beos.cpp ../extfs.cpp extfs_beos.cpp \
|
||||
../user_strings.cpp user_strings_beos.cpp about_window.cpp \
|
||||
$(CPUSRCS)
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS=
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS=be game media device textencoding tracker net
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS=
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS =
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS = ../include SheepDriver SheepNet
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
OPTIMIZE= FULL
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES= FPU_X86 SIZEOF_FLOAT=4 SIZEOF_DOUBLE=8 SIZEOF_LONG_DOUBLE=10
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS =
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS =
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from
|
||||
# a source-level debugger
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS = -fomit-frame-pointer -fno-PIC
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
|
||||
## include the makefile-engine
|
||||
include /boot/system/develop/etc/makefile-engine
|
||||
|
||||
|
||||
# special handling of UAE CPU engine
|
||||
$(OBJ_DIR)/%.o : %.s
|
||||
$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
|
||||
$(OBJ_DIR)/cpuopti: $(OBJ_DIR)/cpuopti.o
|
||||
$(CC) $(LDFLAGS) -o $(OBJ_DIR)/cpuopti $(OBJ_DIR)/cpuopti.o
|
||||
$(OBJ_DIR)/build68k: $(OBJ_DIR)/build68k.o
|
||||
$(CC) $(LDFLAGS) -o $(OBJ_DIR)/build68k $(OBJ_DIR)/build68k.o
|
||||
$(OBJ_DIR)/gencpu: $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o
|
||||
$(CC) $(LDFLAGS) -o $(OBJ_DIR)/gencpu $(OBJ_DIR)/gencpu.o $(OBJ_DIR)/readcpu.o $(OBJ_DIR)/cpudefs.o
|
||||
cpudefs.cpp: $(OBJ_DIR)/build68k ../uae_cpu/table68k
|
||||
$(OBJ_DIR)/build68k <../uae_cpu/table68k >cpudefs.cpp
|
||||
cpuemu.cpp: $(OBJ_DIR)/gencpu
|
||||
$(OBJ_DIR)/gencpu
|
||||
cpustbl.cpp: cpuemu.cpp
|
||||
cputbl.h: cpuemu.cpp
|
||||
cpufast.s: cpuemu.cpp $(OBJ_DIR)/cpuopti
|
||||
$(CXX) $(INCLUDES) -S $(CFLAGS) $< -o cputmp.s
|
||||
$(OBJ_DIR)/cpuopti <cputmp.s >$@ || mv cputmp.s $@
|
||||
rm -f cputmp.s
|
||||
|
||||
streifenfrei:
|
||||
-rm -f $(OBJ_DIR)/gencpu $(OBJ_DIR)/build68k $(OBJ_DIR)/cpuopti
|
||||
-rm -f cpuemu.cpp cpudefs.cpp cputmp.s cpufast*.s cpustbl.cpp cputbl.h
|
|
@ -1,117 +0,0 @@
|
|||
## BeOS Generic Makefile v2.1 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME= sheep
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE= DRIVER
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
SRCS= sheep_driver.c
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS=
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS=
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS=
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS =
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS =
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
OPTIMIZE= FULL
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES=
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS =
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS =
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from a source-level
|
||||
# debugger. Note that this will disable all optimzation.
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS =
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
|
||||
## include the makefile-engine
|
||||
include /boot/develop/etc/makefile-engine
|
||||
|
||||
install: $(TARGET)
|
||||
cp $(TARGET) /boot/home/config/add-ons/kernel/drivers/bin
|
||||
ln -sf /boot/home/config/add-ons/kernel/drivers/bin/$(NAME) /boot/home/config/add-ons/kernel/drivers/dev/$(NAME)
|
||||
|
||||
uninstall:
|
||||
rm /boot/home/config/add-ons/kernel/drivers/bin/$(NAME)
|
||||
rm /boot/home/config/add-ons/kernel/drivers/dev/$(NAME)
|
|
@ -1,476 +0,0 @@
|
|||
/*
|
||||
* sheep_driver.c - Low memory and ROM access driver for SheepShaver and
|
||||
* Basilisk II on PowerPC systems
|
||||
*
|
||||
* SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer
|
||||
* Basilisk II (C) 1997-2002 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef __i386__
|
||||
#error The sheep driver only runs on PowerPC machines.
|
||||
#endif
|
||||
|
||||
#include <drivers/KernelExport.h>
|
||||
#include <drivers/Drivers.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "sheep_driver.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#if DEBUG==1
|
||||
#define bug pprintf
|
||||
#elif DEBUG==2
|
||||
#define bug dprintf
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#define D(x) (x)
|
||||
#else
|
||||
#define D(x) ;
|
||||
#endif
|
||||
|
||||
#define PORT_NAME "sheep_driver installed"
|
||||
|
||||
|
||||
/*
|
||||
* For debugging
|
||||
*/
|
||||
|
||||
static int pprintf(const char* format, ...)
|
||||
{
|
||||
port_id PortNum;
|
||||
int len, ret;
|
||||
char Buffer[1024];
|
||||
va_list ap;
|
||||
|
||||
if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND)
|
||||
return(PortNum);
|
||||
for (len=0; len<1024; len++)
|
||||
Buffer[len]='\0';
|
||||
va_start(ap, format);
|
||||
vsprintf(Buffer, format, ap);
|
||||
ret = write_port(PortNum, 0, Buffer, strlen(Buffer));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Page table functions
|
||||
*/
|
||||
|
||||
static uint32 *pte_address = 0;
|
||||
static uint32 vsid;
|
||||
static uint32 table_size;
|
||||
|
||||
static status_t map_page(uint32 ea, uint32 ra, uint32 **free_pte, uint32 bits)
|
||||
{
|
||||
int i;
|
||||
int pte_class;
|
||||
uint32 hash1, hash2, api, *pteg1, *pteg2;
|
||||
|
||||
D(bug("Trying to map EA %p -> RA %p\n", ea, ra));
|
||||
|
||||
// Find PTEG addresses for given EA
|
||||
hash1 = (vsid & 0x7ffff) ^ ((ea >> 12) & 0xffff);
|
||||
hash2 = ~hash1 & 0x7ffff;
|
||||
api = (ea >> 22) & 0x3f;
|
||||
pteg1 = (uint32 *)((uint32)pte_address + ((hash1 << 6) & (table_size - 1)));
|
||||
pteg2 = (uint32 *)((uint32)pte_address + ((hash2 << 6) & (table_size - 1)));
|
||||
D(bug("PTEG1 at %p, PTEG2 at %p\n", pteg1, pteg2));
|
||||
|
||||
// Search all 8 PTEs of each PTEG
|
||||
*free_pte = NULL;
|
||||
pte_class = 0;
|
||||
for (i=0; i<8; i++) {
|
||||
D(bug(" found %08lx %08lx\n", pteg1[i*2], pteg1[i*2+1]));
|
||||
if (pteg1[i*2] == (0x80000000 | (vsid << 7) | (pte_class << 6) | api)) {
|
||||
*free_pte = pteg1 + i*2;
|
||||
D(bug(" existing PTE found (PTEG1)\n"));
|
||||
break;
|
||||
} else if (!pteg1[i*2]) {
|
||||
*free_pte = pteg1 + i*2;
|
||||
D(bug(" free PTE found (PTEG1)\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*free_pte == NULL) {
|
||||
pte_class = 1;
|
||||
for (i=0; i<8; i++) {
|
||||
D(bug(" found %08lx %08lx\n", pteg2[i*2], pteg2[i*2+1]));
|
||||
if (pteg2[i*2] == (0x80000000 | (vsid << 7) | (pte_class << 6) | api)) {
|
||||
*free_pte = pteg2 + i*2;
|
||||
D(bug(" existing PTE found (PTEG2)\n"));
|
||||
break;
|
||||
} else if (!pteg2[i*2]) {
|
||||
*free_pte = pteg2 + i*2;
|
||||
D(bug(" free PTE found (PTEG2)\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remap page
|
||||
if (*free_pte == NULL) {
|
||||
D(bug(" No free PTE found :-(\m"));
|
||||
return B_DEVICE_FULL;
|
||||
} else {
|
||||
(*free_pte)[0] = 0x80000000 | (vsid << 7) | (pte_class << 6) | api;
|
||||
(*free_pte)[1] = ra | bits;
|
||||
D(bug(" written %08lx %08lx to PTE\n", (*free_pte)[0], (*free_pte)[1]));
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static status_t remap_page(uint32 *free_pte, uint32 ra, uint32 bits)
|
||||
{
|
||||
D(bug("Remapping PTE %p -> RA %p\n", free_pte, ra));
|
||||
|
||||
// Remap page
|
||||
if (free_pte == NULL) {
|
||||
D(bug(" Invalid PTE :-(\n"));
|
||||
return B_BAD_ADDRESS;
|
||||
} else {
|
||||
free_pte[1] = ra | bits;
|
||||
D(bug(" written %08lx %08lx to PTE\n", free_pte[0], free_pte[1]));
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Foward declarations for hook functions
|
||||
*/
|
||||
|
||||
static status_t sheep_open(const char *name, uint32 flags, void **cookie);
|
||||
static status_t sheep_close(void *cookie);
|
||||
static status_t sheep_free(void *cookie);
|
||||
static status_t sheep_control(void *cookie, uint32 op, void *data, size_t len);
|
||||
static status_t sheep_read(void *cookie, off_t pos, void *data, size_t *len);
|
||||
static status_t sheep_write(void *cookie, off_t pos, const void *data, size_t *len);
|
||||
|
||||
|
||||
/*
|
||||
* Version of our driver
|
||||
*/
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
|
||||
/*
|
||||
* Device_hooks structure - has function pointers to the
|
||||
* various entry points for device operations
|
||||
*/
|
||||
|
||||
static device_hooks my_device_hooks = {
|
||||
&sheep_open,
|
||||
&sheep_close,
|
||||
&sheep_free,
|
||||
&sheep_control,
|
||||
&sheep_read,
|
||||
&sheep_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* List of device names to be returned by publish_devices()
|
||||
*/
|
||||
|
||||
static char *device_name_list[] = {
|
||||
"sheep",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Init - do nothing
|
||||
*/
|
||||
|
||||
status_t init_hardware(void)
|
||||
{
|
||||
#if DEBUG==2
|
||||
set_dprintf_enabled(true);
|
||||
#endif
|
||||
D(bug("init_hardware()\n"));
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
status_t init_driver(void)
|
||||
{
|
||||
D(bug("init_driver()\n"));
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
void uninit_driver(void)
|
||||
{
|
||||
D(bug("uninit_driver()\n"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* publish_devices - return list of device names implemented by this driver
|
||||
*/
|
||||
|
||||
const char **publish_devices(void)
|
||||
{
|
||||
return device_name_list;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* find_device - return device hooks for a specific device name
|
||||
*/
|
||||
|
||||
device_hooks *find_device(const char *name)
|
||||
{
|
||||
if (!strcmp(name, device_name_list[0]))
|
||||
return &my_device_hooks;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sheep_open - hook function for the open call.
|
||||
*/
|
||||
|
||||
static status_t sheep_open(const char *name, uint32 flags, void **cookie)
|
||||
{
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sheep_close - hook function for the close call.
|
||||
*/
|
||||
|
||||
static status_t sheep_close(void *cookie)
|
||||
{
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sheep_free - hook function to free the cookie returned
|
||||
* by the open hook. Since the open hook did not return
|
||||
* a cookie, this is a no-op.
|
||||
*/
|
||||
|
||||
static status_t sheep_free(void *cookie)
|
||||
{
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sheep_control - hook function for the ioctl call
|
||||
*/
|
||||
|
||||
static asm void inval_tlb(uint32 ea)
|
||||
{
|
||||
isync
|
||||
tlbie r3
|
||||
sync
|
||||
blr
|
||||
}
|
||||
|
||||
static asm void tlbsync(void)
|
||||
{
|
||||
machine 604
|
||||
tlbsync
|
||||
sync
|
||||
blr
|
||||
}
|
||||
|
||||
static status_t sheep_control(void *cookie, uint32 op, void *data, size_t len)
|
||||
{
|
||||
static void *block;
|
||||
static void *block_aligned;
|
||||
physical_entry pe[2];
|
||||
system_info sysinfo;
|
||||
area_id id;
|
||||
area_info info;
|
||||
cpu_status cpu_st;
|
||||
status_t res;
|
||||
uint32 ra0, ra1;
|
||||
uint32 *free_pte_0, *free_pte_1;
|
||||
int i;
|
||||
|
||||
D(bug("control(%d) data %p, len %08x\n", op, data, len));
|
||||
|
||||
switch (op) {
|
||||
case SHEEP_UP:
|
||||
|
||||
// Already messed up? Then do nothing now
|
||||
if (find_port(PORT_NAME) != B_NAME_NOT_FOUND)
|
||||
return B_NO_ERROR;
|
||||
|
||||
// Get system info
|
||||
get_system_info(&sysinfo);
|
||||
|
||||
// Prepare replacement memory
|
||||
block = malloc(B_PAGE_SIZE * 3);
|
||||
D(bug("3 pages malloc()ed at %p\n", block));
|
||||
block_aligned = (void *)(((uint32)block + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE-1));
|
||||
D(bug("Address aligned to %p\n", block_aligned));
|
||||
res = lock_memory(block_aligned, B_PAGE_SIZE * 2, 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
// Get memory mapping
|
||||
D(bug("Memory locked\n"));
|
||||
res = get_memory_map(block_aligned, B_PAGE_SIZE * 2, pe, 2);
|
||||
D(bug("get_memory_map returned %d\n", res));
|
||||
if (res != B_NO_ERROR)
|
||||
return res;
|
||||
|
||||
// Find PTE table area
|
||||
id = find_area("pte_table");
|
||||
get_area_info(id, &info);
|
||||
pte_address = (uint32 *)info.address;
|
||||
D(bug("PTE table seems to be at %p\n", pte_address));
|
||||
table_size = info.size;
|
||||
D(bug("PTE table size: %dKB\n", table_size / 1024));
|
||||
|
||||
// Disable interrupts
|
||||
cpu_st = disable_interrupts();
|
||||
|
||||
// Find vsid and real addresses of replacement memory
|
||||
for (i=0; i<table_size/8; i++) {
|
||||
if (((uint32)pe[0].address & 0xfffff000)==(pte_address[i*2+1]&0xfffff000)) {
|
||||
D(bug("Found page 0 PtePos %04x V%x VSID %03x H%x API %02x RPN %03x R%1x C%1x WIMG%1x PP%1x \n",
|
||||
i << 2,
|
||||
((pte_address[i*2]&0x80000000) >> 31),((pte_address[i*2]&0x7fffff80) >> 7),
|
||||
((pte_address[i*2]&0x00000040) >> 6),(pte_address[i*2] & 0x3f),
|
||||
((pte_address[i*2+1]&0xfffff000) >> 12),((pte_address[i*2+1]&0x00000100) >> 8),
|
||||
((pte_address[i*2+1]&0x00000080) >> 7),((pte_address[i*2+1]&0x00000078) >> 3),
|
||||
(pte_address[i*2+1]&0x00000003)));
|
||||
vsid = (pte_address[i*2]&0x7fffff80) >> 7;
|
||||
ra0 = (uint32)pe[0].address & 0xfffff000;
|
||||
}
|
||||
if ((uint32)pe[0].size == B_PAGE_SIZE) {
|
||||
if (((uint32)pe[1].address & 0xfffff000)==(pte_address[i*2+1]&0xfffff000)) {
|
||||
D(bug("Found page 1f PtePos %04x V%x VSID %03x H%x API %02x RPN %03x R%1x C%1x WIMG%1x PP%1x \n",
|
||||
i << 2,
|
||||
((pte_address[i*2]&0x80000000) >> 31), ((pte_address[i*2]&0x7fffff80) >> 7),
|
||||
((pte_address[i*2]&0x00000040) >> 6), (pte_address[i*2] & 0x3f),
|
||||
((pte_address[i*2+1]&0xfffff000) >> 12), ((pte_address[i*2+1]&0x00000100) >> 8),
|
||||
((pte_address[i*2+1]&0x00000080) >> 7), ((pte_address[i*2+1]&0x00000078) >> 3),
|
||||
(pte_address[i*2+1]&0x00000003)));
|
||||
ra1 = (uint32)pe[1].address & 0xfffff000;
|
||||
}
|
||||
} else {
|
||||
if ((((uint32)pe[0].address + B_PAGE_SIZE) & 0xfffff000)==(pte_address[i*2+1]&0xfffff000)) {
|
||||
D(bug("Found page 1d PtePos %04x V%x VSID %03x H%x API %02x RPN %03x R%1x C%1x WIMG%1x PP%1x \n",
|
||||
i << 2,
|
||||
((pte_address[i*2]&0x80000000) >> 31), ((pte_address[i*2]&0x7fffff80) >> 7),
|
||||
((pte_address[i*2]&0x00000040) >> 6), (pte_address[i*2] & 0x3f),
|
||||
((pte_address[i*2+1]&0xfffff000) >> 12), ((pte_address[i*2+1]&0x00000100) >> 8),
|
||||
((pte_address[i*2+1]&0x00000080) >> 7), ((pte_address[i*2+1]&0x00000078) >> 3),
|
||||
(pte_address[i*2+1]&0x00000003)));
|
||||
ra1 = ((uint32)pe[0].address + B_PAGE_SIZE) & 0xfffff000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Map low memory for emulator
|
||||
free_pte_0 = NULL;
|
||||
free_pte_1 = NULL;
|
||||
__sync();
|
||||
__isync();
|
||||
inval_tlb(0);
|
||||
inval_tlb(B_PAGE_SIZE);
|
||||
if (sysinfo.cpu_type != B_CPU_PPC_603 && sysinfo.cpu_type != B_CPU_PPC_603e)
|
||||
tlbsync();
|
||||
res = map_page(0, ra0, &free_pte_0, 0x12);
|
||||
if (res == B_NO_ERROR)
|
||||
res = map_page(B_PAGE_SIZE, ra1, &free_pte_1, 0x12);
|
||||
inval_tlb(0);
|
||||
inval_tlb(B_PAGE_SIZE);
|
||||
if (sysinfo.cpu_type != B_CPU_PPC_603 && sysinfo.cpu_type != B_CPU_PPC_603e)
|
||||
tlbsync();
|
||||
__sync();
|
||||
__isync();
|
||||
|
||||
// Restore interrupts
|
||||
restore_interrupts(cpu_st);
|
||||
|
||||
// Create port so we know that messing was successful
|
||||
set_port_owner(create_port(1, PORT_NAME), B_SYSTEM_TEAM);
|
||||
return B_NO_ERROR;
|
||||
|
||||
case SHEEP_DOWN:
|
||||
return B_NO_ERROR;
|
||||
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sheep_read - hook function for the read call
|
||||
*/
|
||||
|
||||
static status_t sheep_read(void *cookie, off_t pos, void *data, size_t *len)
|
||||
{
|
||||
void *rom_adr;
|
||||
area_id area;
|
||||
system_info info;
|
||||
|
||||
D(bug("read() pos %Lx, data %p, len %08x\n", pos, data, *len));
|
||||
|
||||
get_system_info(&info);
|
||||
if (info.platform_type == B_BEBOX_PLATFORM) {
|
||||
*len = 0;
|
||||
return B_ERROR;
|
||||
}
|
||||
if (*len != 0x400000 && pos != 0) {
|
||||
*len = 0;
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
area = map_physical_memory("mac_rom", (void *)0xff000000, 0x00400000, B_ANY_KERNEL_ADDRESS, B_READ_AREA, &rom_adr);
|
||||
D(bug("Mapped ROM to %p, area id %d\n", rom_adr, area));
|
||||
if (area < 0) {
|
||||
*len = 0;
|
||||
return area;
|
||||
}
|
||||
D(bug("Copying ROM\n"));
|
||||
memcpy(data, rom_adr, *len);
|
||||
D(bug("Deleting area\n"));
|
||||
delete_area(area);
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* sheep_write - hook function for the write call
|
||||
*/
|
||||
|
||||
static status_t sheep_write(void *cookie, off_t pos, const void *data, size_t *len)
|
||||
{
|
||||
D(bug("write() pos %Lx, data %p, len %08x\n", pos, data, *len));
|
||||
return B_READ_ONLY_DEVICE;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* sheep_driver.h - Low memory and ROM access driver for SheepShaver and
|
||||
* Basilisk II on PowerPC systems
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SHEEP_DRIVER_H
|
||||
#define SHEEP_DRIVER_H
|
||||
|
||||
#include <drivers/Drivers.h>
|
||||
|
||||
enum {
|
||||
SHEEP_UP = B_DEVICE_OP_CODES_END + 1,
|
||||
SHEEP_DOWN
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,115 +0,0 @@
|
|||
## BeOS Generic Makefile v2.1 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME= sheep_net
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE= SHARED
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
SRCS= sheep_net.cpp
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS=
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS= netdev
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS=
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS =
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS =
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
OPTIMIZE= FULL
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES=
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS =
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS =
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from a source-level
|
||||
# debugger. Note that this will disable all optimzation.
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS =
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
|
||||
## include the makefile-engine
|
||||
include /boot/develop/etc/makefile-engine
|
||||
|
||||
install: $(TARGET)
|
||||
cp $(TARGET) /boot/beos/system/add-ons/net_server/$(NAME)
|
||||
|
||||
uninstall:
|
||||
rm /boot/beos/system/add-ons/net_server/$(NAME)
|
|
@ -1,294 +0,0 @@
|
|||
/*
|
||||
* sheep_net.cpp - Net server add-on for SheepShaver and Basilisk II
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <KernelKit.h>
|
||||
#include <SupportKit.h>
|
||||
#include <add-ons/net_server/NetDevice.h>
|
||||
#include <add-ons/net_server/NetProtocol.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "sheep_net.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
#if DEBUG==1
|
||||
#define bug pprintf
|
||||
#elif DEBUG==2
|
||||
#define bug kprintf
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#define D(x) (x)
|
||||
#else
|
||||
#define D(x) ;
|
||||
#endif
|
||||
|
||||
static int pprintf(const char* format, ...)
|
||||
{
|
||||
port_id PortNum;
|
||||
int len,Ret;
|
||||
char Buffer[1024];
|
||||
va_list ap;
|
||||
|
||||
if ((PortNum = find_port("PortLogger")) == B_NAME_NOT_FOUND)
|
||||
return(PortNum);
|
||||
for (len=0; len<1024; len++)
|
||||
Buffer[len]='\0';
|
||||
va_start(ap, format);
|
||||
vsprintf(Buffer, format, ap);
|
||||
Ret = write_port(PortNum, 0, Buffer, strlen(Buffer));
|
||||
return(Ret);
|
||||
}
|
||||
|
||||
|
||||
// Constants
|
||||
#define NETDUMP_PRIO 1 // Default is 0
|
||||
|
||||
const uint32 buffer_size = (sizeof(net_buffer) / B_PAGE_SIZE + 1) * B_PAGE_SIZE;
|
||||
|
||||
|
||||
// SheepNet add-on object
|
||||
class SheepNetAddOn : public BNetProtocol, BPacketHandler {
|
||||
public:
|
||||
void AddDevice(BNetDevice *dev, const char *name);
|
||||
bool PacketReceived(BNetPacket *buf, BNetDevice *dev);
|
||||
};
|
||||
|
||||
|
||||
// Global variables
|
||||
static bool shutdown_now = false;
|
||||
static bool active = false;
|
||||
|
||||
static thread_id write_thread; // Packet writer
|
||||
static sem_id write_sem; // Semaphore to trigger packet writing
|
||||
static BNetDevice *EtherCard = NULL; // The Ethernet card we are attached to
|
||||
static area_id buffer_area; // Packet buffer area
|
||||
static net_buffer *net_buffer_ptr; // Pointer to packet buffer
|
||||
|
||||
static uint32 rd_pos; // Current read position in packet buffer
|
||||
static uint32 wr_pos; // Current write position in packet buffer
|
||||
|
||||
|
||||
/*
|
||||
* Clear packet buffer
|
||||
*/
|
||||
|
||||
static void clear(void)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<READ_PACKET_COUNT;i++) {
|
||||
net_buffer_ptr->read[i].cmd = 0;
|
||||
net_buffer_ptr->read[i].length = 0;
|
||||
net_buffer_ptr->read[i].card = 0;
|
||||
net_buffer_ptr->read[i].reserved = 0;
|
||||
}
|
||||
for (i=0;i<WRITE_PACKET_COUNT;i++) {
|
||||
net_buffer_ptr->write[i].cmd = 0;
|
||||
net_buffer_ptr->write[i].length = 0;
|
||||
net_buffer_ptr->write[i].card = 0;
|
||||
net_buffer_ptr->write[i].reserved = 0;
|
||||
}
|
||||
rd_pos = wr_pos = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Packet writer thread
|
||||
*/
|
||||
|
||||
static status_t write_packet_func(void *arg)
|
||||
{
|
||||
while (!shutdown_now) {
|
||||
|
||||
// Read and execute command
|
||||
net_packet *p = &net_buffer_ptr->write[wr_pos];
|
||||
while (p->cmd & IN_USE) {
|
||||
D(bug("wp: %d\n", wr_pos));
|
||||
switch (p->cmd >> 8) {
|
||||
|
||||
case ACTIVATE_SHEEP_NET:
|
||||
D(bug("activate sheep-net\n"));
|
||||
active = false;
|
||||
clear();
|
||||
active = true;
|
||||
goto next;
|
||||
|
||||
case DEACTIVATE_SHEEP_NET:
|
||||
D(bug("deactivate sheep-net\n"));
|
||||
active = false;
|
||||
clear();
|
||||
goto next;
|
||||
|
||||
case SHUTDOWN_SHEEP_NET:
|
||||
D(bug("shutdown sheep-net\n"));
|
||||
active = false;
|
||||
clear();
|
||||
shutdown_now = true;
|
||||
goto next;
|
||||
|
||||
case ADD_MULTICAST: {
|
||||
const char *data = (const char *)p->data;
|
||||
D(bug("add multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5]));
|
||||
if (active) {
|
||||
status_t result;
|
||||
if ((result = EtherCard->AddMulticastAddress(data)) != B_OK) {
|
||||
// !! handle error !! error while creating multicast address
|
||||
D(bug("error while creating multicast address %d\n", result));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case REMOVE_MULTICAST: {
|
||||
const char *data = (const char *)p->data;
|
||||
D(bug("remove multicast %02x %02x %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3], data[4], data[5]));
|
||||
if (active) {
|
||||
status_t result;
|
||||
if ((result = EtherCard->RemoveMulticastAddress(data)) != B_OK) {
|
||||
// !! handle error !! error while removing multicast address
|
||||
D(bug("error while removing multicast address %d\n", result));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SHEEP_PACKET: {
|
||||
uint32 length = p->length;
|
||||
// D(bug("sheep packet %d\n", length));
|
||||
if (active) {
|
||||
BStandardPacket *packet = new BStandardPacket(length);
|
||||
packet->Write(0, (const char *)p->data, length);
|
||||
EtherCard->SendPacket(packet);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
D(bug("error: unknown port packet type\n"));
|
||||
break;
|
||||
}
|
||||
p->cmd = 0; // Free packet
|
||||
wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
|
||||
p = &net_buffer_ptr->write[wr_pos];
|
||||
}
|
||||
|
||||
// Wait for next packet
|
||||
next: acquire_sem_etc(write_sem, 1, B_TIMEOUT, 25000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Init the net add-on
|
||||
*/
|
||||
|
||||
static void init_addon()
|
||||
{
|
||||
int i;
|
||||
D(bug("init sheep-net\n"));
|
||||
|
||||
// Create packet buffer
|
||||
if ((buffer_area = create_area("packet buffer", (void **)&net_buffer_ptr, B_ANY_ADDRESS, buffer_size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_NO_ERROR) {
|
||||
D(bug("FATAL ERROR: can't create shared area\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Init packet buffer
|
||||
clear();
|
||||
EtherCard->Address((char *)net_buffer_ptr->ether_addr);
|
||||
net_buffer_ptr->read_sem = -1;
|
||||
net_buffer_ptr->read_ofs = (uint32)(net_buffer_ptr->read) - (uint32)net_buffer_ptr;
|
||||
net_buffer_ptr->read_packet_size = sizeof(net_packet);
|
||||
net_buffer_ptr->read_packet_count = READ_PACKET_COUNT;
|
||||
if ((write_sem = create_sem(0, "ether write")) < B_NO_ERROR) {
|
||||
D(bug("FATAL ERROR: can't create semaphore\n"));
|
||||
return;
|
||||
}
|
||||
net_buffer_ptr->write_sem = write_sem;
|
||||
net_buffer_ptr->write_ofs = (uint32)(net_buffer_ptr->write) - (uint32)net_buffer_ptr;
|
||||
net_buffer_ptr->write_packet_size = sizeof(net_packet);
|
||||
net_buffer_ptr->write_packet_count = WRITE_PACKET_COUNT;
|
||||
|
||||
// Start packet writer thread
|
||||
write_thread = spawn_thread(write_packet_func, "sheep_net ether write", B_URGENT_DISPLAY_PRIORITY, NULL);
|
||||
resume_thread(write_thread);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add-on attached to Ethernet card
|
||||
*/
|
||||
|
||||
void SheepNetAddOn::AddDevice(BNetDevice *dev, const char *name)
|
||||
{
|
||||
if (dev->Type() != B_ETHER_NET_DEVICE)
|
||||
return;
|
||||
if (EtherCard != NULL) {
|
||||
// !! handle error !! support for multiple ethernet cards ...
|
||||
D(bug("error: SheepShaver doesn't support multiple Ethernetcards !\n"));
|
||||
return;
|
||||
}
|
||||
EtherCard = dev;
|
||||
init_addon();
|
||||
register_packet_handler(this, dev, NETDUMP_PRIO);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ethernet packet received
|
||||
*/
|
||||
|
||||
bool SheepNetAddOn::PacketReceived(BNetPacket *pkt, BNetDevice *dev)
|
||||
{
|
||||
if (shutdown_now) {
|
||||
unregister_packet_handler(this, dev);
|
||||
return false;
|
||||
}
|
||||
// D(bug("read_packet_func %d\n", pkt->Size()));
|
||||
if (active) {
|
||||
D(bug("rp: %d\n", rd_pos));
|
||||
net_packet *p = &net_buffer_ptr->read[rd_pos];
|
||||
if (p->cmd & IN_USE) {
|
||||
D(bug("error: full read buffer ... lost packet\n"));
|
||||
} else {
|
||||
memcpy(p->data, pkt->Data(), pkt->Size());
|
||||
p->length = pkt->Size();
|
||||
p->cmd = IN_USE | (SHEEP_PACKET << 8);
|
||||
rd_pos = (rd_pos + 1) % READ_PACKET_COUNT;
|
||||
release_sem(net_buffer_ptr->read_sem);
|
||||
}
|
||||
}
|
||||
//D(bug("%02x %02x %02x %02x %02x %02x", (uchar) (pkt->Data())[0],(uchar) (pkt->Data())[1],(uchar) (pkt->Data())[2],(uchar) (pkt->Data())[3],(uchar) (pkt->Data())[4],(uchar) (pkt->Data())[5]));
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma export on
|
||||
extern "C" BNetProtocol *open_protocol(const char *device)
|
||||
{
|
||||
SheepNetAddOn *dev = new SheepNetAddOn;
|
||||
return dev;
|
||||
}
|
||||
#pragma export off
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* sheep_net.h - Net server add-on for SheepShaver and Basilisk II
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SHEEP_NET_H
|
||||
#define SHEEP_NET_H
|
||||
|
||||
// Net buffer dimensions
|
||||
#define READ_PACKET_COUNT 10
|
||||
#define WRITE_PACKET_COUNT 10
|
||||
|
||||
// Net packet
|
||||
struct net_packet {
|
||||
uint32 cmd; // Command
|
||||
uint32 length; // Data length
|
||||
uint32 card; // Network card ID
|
||||
uint32 reserved;
|
||||
uint8 data[1584];
|
||||
};
|
||||
|
||||
// Net buffer (shared area)
|
||||
struct net_buffer {
|
||||
uint8 ether_addr[6]; // Ethernet address
|
||||
uint8 filler1[2];
|
||||
sem_id read_sem; // Semaphore for read packets
|
||||
uint32 read_ofs;
|
||||
uint32 read_packet_size;
|
||||
uint32 read_packet_count;
|
||||
sem_id write_sem; // Semaphore for write packets
|
||||
uint32 write_ofs;
|
||||
uint32 write_packet_size;
|
||||
uint32 write_packet_count;
|
||||
uint8 filler[24];
|
||||
net_packet read[READ_PACKET_COUNT];
|
||||
net_packet write[WRITE_PACKET_COUNT];
|
||||
};
|
||||
|
||||
// Packet commands
|
||||
#define SHEEP_PACKET 0
|
||||
#define ADD_MULTICAST 1
|
||||
#define REMOVE_MULTICAST 2
|
||||
#define ACTIVATE_SHEEP_NET 8
|
||||
#define DEACTIVATE_SHEEP_NET 9
|
||||
#define SHUTDOWN_SHEEP_NET 10
|
||||
|
||||
#define IN_USE 1
|
||||
|
||||
#endif
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* about_window.cpp - "About" window
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <InterfaceKit.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "version.h"
|
||||
#include "user_strings.h"
|
||||
|
||||
/*
|
||||
* Display "About" window
|
||||
*/
|
||||
|
||||
void ShowAboutWindow(void)
|
||||
{
|
||||
char str[512];
|
||||
sprintf(str,
|
||||
"Basilisk II\nVersion %d.%d\n\n"
|
||||
"Copyright " B_UTF8_COPYRIGHT " 1997-2008 Christian Bauer et al.\n"
|
||||
"E-mail: Christian.Bauer@uni-mainz.de\n"
|
||||
"http://www.uni-mainz.de/~bauec002/B2Main.html\n\n"
|
||||
"Basilisk II comes with ABSOLUTELY NO\n"
|
||||
"WARRANTY. This is free software, and\n"
|
||||
"you are welcome to redistribute it\n"
|
||||
"under the terms of the GNU General\n"
|
||||
"Public License.\n",
|
||||
VERSION_MAJOR, VERSION_MINOR
|
||||
);
|
||||
BAlert *about = new BAlert("", str, GetString(STR_OK_BUTTON), NULL, NULL, B_WIDTH_FROM_LABEL);
|
||||
BTextView *theText = about->TextView();
|
||||
if (theText) {
|
||||
theText->SetStylable(true);
|
||||
theText->Select(0, 11);
|
||||
BFont ourFont;
|
||||
theText->SetFontAndColor(be_bold_font);
|
||||
theText->GetFontAndColor(2, &ourFont, NULL);
|
||||
ourFont.SetSize(24);
|
||||
theText->SetFontAndColor(&ourFont);
|
||||
}
|
||||
about->Go();
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* about_window.h - "About" window
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef ABOUT_WINDOW_H
|
||||
#define ABOUT_WINDOW_H
|
||||
|
||||
// Display "About" window
|
||||
extern void ShowAboutWindow(void);
|
||||
|
||||
#endif
|
|
@ -1,342 +0,0 @@
|
|||
/*
|
||||
* audio_beos.cpp - Audio support, BeOS implementation
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Portions written by Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <KernelKit.h>
|
||||
#include <MediaKit.h>
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "audio.h"
|
||||
#include "audio_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Global variables
|
||||
static int audio_irq_done_sem = -1; // Signal from interrupt to streaming thread: data block read
|
||||
static BSoundPlayer *the_player;
|
||||
|
||||
// Prototypes
|
||||
static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format);
|
||||
|
||||
|
||||
/*
|
||||
* Audio manager thread (for calling media kit functions;
|
||||
* this is not safe under R4 when running on the MacOS stack in kernel space)
|
||||
*/
|
||||
|
||||
// Message constants
|
||||
const uint32 MSG_QUIT_AUDIO_MANAGER = 'quit';
|
||||
const uint32 MSG_ENTER_STREAM = 'entr';
|
||||
const uint32 MSG_EXIT_STREAM = 'exit';
|
||||
const uint32 MSG_GET_VOLUME = 'getv';
|
||||
const uint32 MSG_SET_VOLUME = 'setv';
|
||||
|
||||
static thread_id am_thread = -1;
|
||||
static sem_id am_done_sem = -1;
|
||||
|
||||
static volatile float am_volume;
|
||||
|
||||
static status_t audio_manager(void *arg)
|
||||
{
|
||||
for (;;) {
|
||||
|
||||
// Receive message
|
||||
thread_id sender;
|
||||
uint32 code = receive_data(&sender, NULL, 0);
|
||||
D(bug("Audio manager received %08lx\n", code));
|
||||
switch (code) {
|
||||
case MSG_QUIT_AUDIO_MANAGER:
|
||||
return 0;
|
||||
|
||||
case MSG_ENTER_STREAM:
|
||||
the_player->Start();
|
||||
break;
|
||||
|
||||
case MSG_EXIT_STREAM:
|
||||
the_player->Stop();
|
||||
break;
|
||||
|
||||
case MSG_GET_VOLUME:
|
||||
am_volume = the_player->Volume();
|
||||
break;
|
||||
|
||||
case MSG_SET_VOLUME:
|
||||
the_player->SetVolume(am_volume);
|
||||
break;
|
||||
}
|
||||
|
||||
// Acknowledge
|
||||
release_sem(am_done_sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
// Set AudioStatus to reflect current audio stream format
|
||||
static void set_audio_status_format(void)
|
||||
{
|
||||
AudioStatus.sample_rate = audio_sample_rates[0];
|
||||
AudioStatus.sample_size = audio_sample_sizes[0];
|
||||
AudioStatus.channels = audio_channel_counts[0];
|
||||
}
|
||||
|
||||
void AudioInit(void)
|
||||
{
|
||||
// Init audio status and feature flags
|
||||
audio_sample_rates.push_back(44100 << 16);
|
||||
audio_sample_sizes.push_back(16);
|
||||
audio_channel_counts.push_back(2);
|
||||
set_audio_status_format();
|
||||
AudioStatus.mixer = 0;
|
||||
AudioStatus.num_sources = 0;
|
||||
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
|
||||
|
||||
// Sound disabled in prefs? Then do nothing
|
||||
if (PrefsFindBool("nosound"))
|
||||
return;
|
||||
|
||||
// Init semaphores
|
||||
audio_irq_done_sem = create_sem(0, "Audio IRQ Done");
|
||||
am_done_sem = create_sem(0, "Audio Manager Done");
|
||||
|
||||
// Start audio manager thread
|
||||
am_thread = spawn_thread(audio_manager, "Audio Manager", B_NORMAL_PRIORITY, NULL);
|
||||
resume_thread(am_thread);
|
||||
|
||||
// Start stream
|
||||
media_raw_audio_format format;
|
||||
format.frame_rate = AudioStatus.sample_rate >> 16;
|
||||
format.channel_count = AudioStatus.channels;
|
||||
format.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
format.byte_order = B_MEDIA_BIG_ENDIAN;
|
||||
audio_frames_per_block = 4096;
|
||||
size_t block_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
|
||||
D(bug("AudioInit: block size %d\n", block_size));
|
||||
format.buffer_size = block_size;
|
||||
the_player = new BSoundPlayer(&format, "MacOS Audio", playbuffer_func, NULL, NULL);
|
||||
if (the_player->InitCheck() != B_NO_ERROR) {
|
||||
printf("FATAL: Cannot initialize BSoundPlayer\n");
|
||||
delete the_player;
|
||||
the_player = NULL;
|
||||
return;
|
||||
} else
|
||||
the_player->SetHasData(true);
|
||||
|
||||
// Everything OK
|
||||
audio_open = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void AudioExit(void)
|
||||
{
|
||||
// Stop stream
|
||||
if (the_player) {
|
||||
the_player->Stop();
|
||||
delete the_player;
|
||||
the_player = NULL;
|
||||
}
|
||||
|
||||
// Stop audio manager
|
||||
if (am_thread > 0) {
|
||||
status_t l;
|
||||
send_data(am_thread, MSG_QUIT_AUDIO_MANAGER, NULL, 0);
|
||||
wait_for_thread(am_thread, &l);
|
||||
}
|
||||
|
||||
// Delete semaphores
|
||||
delete_sem(am_done_sem);
|
||||
delete_sem(audio_irq_done_sem);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* First source added, start audio stream
|
||||
*/
|
||||
|
||||
void audio_enter_stream()
|
||||
{
|
||||
while (send_data(am_thread, MSG_ENTER_STREAM, NULL, 0) == B_INTERRUPTED) ;
|
||||
while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Last source removed, stop audio stream
|
||||
*/
|
||||
|
||||
void audio_exit_stream()
|
||||
{
|
||||
while (send_data(am_thread, MSG_EXIT_STREAM, NULL, 0) == B_INTERRUPTED) ;
|
||||
while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Streaming function
|
||||
*/
|
||||
|
||||
static uint32 apple_stream_info; // Mac address of SoundComponentData struct describing next buffer
|
||||
|
||||
static void playbuffer_func(void *arg, void *buf, size_t size, const media_raw_audio_format &format)
|
||||
{
|
||||
// Check if new buffer is available
|
||||
if (acquire_sem_etc(audio_irq_done_sem, 1, B_TIMEOUT, 0) == B_NO_ERROR) {
|
||||
|
||||
// Get size of audio data
|
||||
D(bug("stream: new buffer present\n"));
|
||||
uint32 apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
|
||||
if (apple_stream_info) {
|
||||
size_t work_size = ReadMacInt32(apple_stream_info + scd_sampleCount) * (AudioStatus.sample_size >> 3) * AudioStatus.channels;
|
||||
D(bug("stream: size %d, work_size %d\n", size, work_size));
|
||||
if (work_size > size)
|
||||
work_size = size;
|
||||
|
||||
if (format.format != media_raw_audio_format::B_AUDIO_SHORT) {
|
||||
D(bug("Wrong audio format %04x\n", format.format));
|
||||
return;
|
||||
}
|
||||
|
||||
// Place data into Media Kit buffer
|
||||
Mac2Host_memcpy(buf, ReadMacInt32(apple_stream_info + scd_buffer), work_size);
|
||||
if (work_size != size)
|
||||
memset((uint8 *)buf + work_size, 0, size - work_size);
|
||||
}
|
||||
|
||||
} else
|
||||
memset(buf, 0, size);
|
||||
|
||||
// Trigger audio interrupt to get new buffer
|
||||
if (AudioStatus.num_sources) {
|
||||
D(bug("stream: triggering irq\n"));
|
||||
SetInterruptFlag(INTFLAG_AUDIO);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MacOS audio interrupt, read next data block
|
||||
*/
|
||||
|
||||
void AudioInterrupt(void)
|
||||
{
|
||||
D(bug("AudioInterrupt\n"));
|
||||
|
||||
// Get data from apple mixer
|
||||
if (AudioStatus.mixer) {
|
||||
M68kRegisters r;
|
||||
r.a[0] = audio_data + adatStreamInfo;
|
||||
r.a[1] = AudioStatus.mixer;
|
||||
Execute68k(audio_data + adatGetSourceData, &r);
|
||||
D(bug(" GetSourceData() returns %08lx\n", r.d[0]));
|
||||
} else
|
||||
WriteMacInt32(audio_data + adatStreamInfo, 0);
|
||||
|
||||
// Signal stream function
|
||||
release_sem(audio_irq_done_sem);
|
||||
D(bug("AudioInterrupt done\n"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set sampling parameters
|
||||
* "index" is an index into the audio_sample_rates[] etc. arrays
|
||||
* It is guaranteed that AudioStatus.num_sources == 0
|
||||
*/
|
||||
|
||||
bool audio_set_sample_rate(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool audio_set_sample_size(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool audio_set_channels(int index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get/set audio info
|
||||
*/
|
||||
|
||||
bool audio_get_main_mute(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 audio_get_main_volume(void)
|
||||
{
|
||||
if (audio_open) {
|
||||
while (send_data(am_thread, MSG_GET_VOLUME, NULL, 0) == B_INTERRUPTED) ;
|
||||
while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
|
||||
return int(am_volume * 256.0) * 0x00010001;
|
||||
} else
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
bool audio_get_speaker_mute(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 audio_get_speaker_volume(void)
|
||||
{
|
||||
return 0x01000100;
|
||||
}
|
||||
|
||||
void audio_set_main_mute(bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_set_main_volume(uint32 vol)
|
||||
{
|
||||
if (audio_open) {
|
||||
am_volume = float((vol >> 16) + (vol & 0xffff)) / 512.0;
|
||||
while (send_data(am_thread, MSG_SET_VOLUME, NULL, 0) == B_INTERRUPTED) ;
|
||||
while (acquire_sem(am_done_sem) == B_INTERRUPTED) ;
|
||||
}
|
||||
}
|
||||
|
||||
void audio_set_speaker_mute(bool mute)
|
||||
{
|
||||
}
|
||||
|
||||
void audio_set_speaker_volume(uint32 vol)
|
||||
{
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* clip_beos.cpp - Clipboard handling, BeOS implementation
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <AppKit.h>
|
||||
#include <support/UTF8.h>
|
||||
|
||||
#include "clip.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#define DEBUG 1
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Flag: Don't convert clipboard text
|
||||
static bool no_clip_conversion;
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void ClipInit(void)
|
||||
{
|
||||
no_clip_conversion = PrefsFindBool("noclipconversion");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void ClipExit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac application zeroes clipboard
|
||||
*/
|
||||
|
||||
void ZeroScrap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac application reads clipboard
|
||||
*/
|
||||
|
||||
void GetScrap(void **handle, uint32 type, int32 offset)
|
||||
{
|
||||
D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mac application wrote to clipboard
|
||||
*/
|
||||
|
||||
void PutScrap(uint32 type, void *scrap, int32 length)
|
||||
{
|
||||
D(bug("PutScrap type %08lx, data %08lx, length %ld\n", type, scrap, length));
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case 'TEXT':
|
||||
D(bug(" clipping TEXT\n"));
|
||||
if (be_clipboard->Lock()) {
|
||||
be_clipboard->Clear();
|
||||
BMessage *clipper = be_clipboard->Data();
|
||||
|
||||
if (no_clip_conversion) {
|
||||
|
||||
// Only convert CR->LF
|
||||
char *buf = new char[length];
|
||||
for (int i=0; i<length; i++) {
|
||||
if (i[(char *)scrap] == 13)
|
||||
buf[i] = 10;
|
||||
else
|
||||
buf[i] = i[(char *)scrap];
|
||||
}
|
||||
|
||||
// Add text to Be clipboard
|
||||
clipper->AddData("text/plain", B_MIME_TYPE, buf, length);
|
||||
be_clipboard->Commit();
|
||||
delete[] buf;
|
||||
|
||||
} else {
|
||||
|
||||
// Convert text from Mac charset to UTF-8
|
||||
int32 dest_length = length*3;
|
||||
int32 state = 0;
|
||||
char *buf = new char[dest_length];
|
||||
if (convert_to_utf8(B_MAC_ROMAN_CONVERSION, (char *)scrap, &length, buf, &dest_length, &state) == B_OK) {
|
||||
for (int i=0; i<dest_length; i++)
|
||||
if (buf[i] == 13)
|
||||
buf[i] = 10;
|
||||
|
||||
// Add text to Be clipboard
|
||||
clipper->AddData("text/plain", B_MIME_TYPE, buf, dest_length);
|
||||
be_clipboard->Commit();
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,532 +0,0 @@
|
|||
/*
|
||||
* ether_beos.cpp - Ethernet device driver, BeOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Portions written by Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <KernelKit.h>
|
||||
#include <AppKit.h>
|
||||
#include <StorageKit.h>
|
||||
#include <support/List.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <sys/select.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "macos_util.h"
|
||||
#include "ether.h"
|
||||
#include "ether_defs.h"
|
||||
|
||||
#include "sheep_net.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define MONITOR 0
|
||||
|
||||
|
||||
// List of attached protocols
|
||||
struct NetProtocol {
|
||||
uint16 type;
|
||||
uint32 handler;
|
||||
};
|
||||
|
||||
static BList prot_list;
|
||||
|
||||
|
||||
// Global variables
|
||||
static thread_id read_thread; // Packet reception thread
|
||||
static bool ether_thread_active = true; // Flag for quitting the reception thread
|
||||
|
||||
static area_id buffer_area; // Packet buffer area
|
||||
static net_buffer *net_buffer_ptr; // Pointer to packet buffer
|
||||
static uint32 rd_pos; // Current read position in packet buffer
|
||||
static uint32 wr_pos; // Current write position in packet buffer
|
||||
static sem_id read_sem, write_sem; // Semaphores to trigger packet reading/writing
|
||||
|
||||
static int fd = -1; // UDP socket fd
|
||||
static bool udp_tunnel = false;
|
||||
|
||||
|
||||
// Prototypes
|
||||
static status_t receive_proc(void *data);
|
||||
|
||||
|
||||
/*
|
||||
* Find protocol in list
|
||||
*/
|
||||
|
||||
static NetProtocol *find_protocol(uint16 type)
|
||||
{
|
||||
// All 802.2 types are the same
|
||||
if (type <= 1500)
|
||||
type = 0;
|
||||
|
||||
// Search list (we could use hashing here but there are usually only three
|
||||
// handlers installed: 0x0000 for AppleTalk and 0x0800/0x0806 for TCP/IP)
|
||||
NetProtocol *p;
|
||||
for (int i=0; (p = (NetProtocol *)prot_list.ItemAt(i)) != NULL; i++)
|
||||
if (p->type == type)
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove all protocols
|
||||
*/
|
||||
|
||||
static void remove_all_protocols(void)
|
||||
{
|
||||
NetProtocol *p;
|
||||
while ((p = (NetProtocol *)prot_list.RemoveItem((long)0)) != NULL)
|
||||
delete p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
bool ether_init(void)
|
||||
{
|
||||
// Do nothing if no Ethernet device specified
|
||||
if (PrefsFindString("ether") == NULL)
|
||||
return false;
|
||||
|
||||
// Find net_server team
|
||||
i_wanna_try_that_again:
|
||||
bool found_add_on = false;
|
||||
team_info t_info;
|
||||
int32 t_cookie = 0;
|
||||
image_info i_info;
|
||||
int32 i_cookie = 0;
|
||||
while (get_next_team_info(&t_cookie, &t_info) == B_NO_ERROR) {
|
||||
if (strstr(t_info.args,"net_server")!=NULL) {
|
||||
|
||||
// Check if sheep_net add-on is loaded
|
||||
while (get_next_image_info(t_info.team, &i_cookie, &i_info) == B_NO_ERROR) {
|
||||
if (strstr(i_info.name, "sheep_net") != NULL) {
|
||||
found_add_on = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_add_on) break;
|
||||
}
|
||||
if (!found_add_on) {
|
||||
|
||||
// Search for sheep_net in network config file
|
||||
char str[1024];
|
||||
bool sheep_net_found = false;
|
||||
FILE *fin = fopen("/boot/home/config/settings/network", "r");
|
||||
while (!feof(fin)) {
|
||||
fgets(str, 1024, fin);
|
||||
if (strstr(str, "PROTOCOLS"))
|
||||
if (strstr(str, "sheep_net"))
|
||||
sheep_net_found = true;
|
||||
}
|
||||
fclose(fin);
|
||||
|
||||
// It was found, so something else must be wrong
|
||||
if (sheep_net_found) {
|
||||
WarningAlert(GetString(STR_NO_NET_ADDON_WARN));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not found, inform the user
|
||||
if (!ChoiceAlert(GetString(STR_NET_CONFIG_MODIFY_WARN), GetString(STR_OK_BUTTON), GetString(STR_CANCEL_BUTTON)))
|
||||
return false;
|
||||
|
||||
// Change the network config file and restart the network
|
||||
fin = fopen("/boot/home/config/settings/network", "r");
|
||||
FILE *fout = fopen("/boot/home/config/settings/network.2", "w");
|
||||
bool global_found = false;
|
||||
bool modified = false;
|
||||
while (!feof(fin)) {
|
||||
str[0] = 0;
|
||||
fgets(str, 1024, fin);
|
||||
if (!global_found && strstr(str, "GLOBAL:")) {
|
||||
global_found = true;
|
||||
} else if (global_found && !modified && strstr(str, "PROTOCOLS")) {
|
||||
str[strlen(str)-1] = 0;
|
||||
strcat(str, " sheep_net\n");
|
||||
modified = true;
|
||||
} else if (global_found && !modified && strlen(str) > 2 && str[strlen(str) - 2] == ':') {
|
||||
fputs("\tPROTOCOLS = sheep_net\n", fout);
|
||||
modified = true;
|
||||
}
|
||||
fputs(str, fout);
|
||||
}
|
||||
if (!modified)
|
||||
fputs("\tPROTOCOLS = sheep_net\n", fout);
|
||||
fclose(fout);
|
||||
fclose(fin);
|
||||
remove("/boot/home/config/settings/network.orig");
|
||||
rename("/boot/home/config/settings/network", "/boot/home/config/settings/network.orig");
|
||||
rename("/boot/home/config/settings/network.2", "/boot/home/config/settings/network");
|
||||
|
||||
app_info ai;
|
||||
if (be_roster->GetAppInfo("application/x-vnd.Be-NETS", &ai) == B_OK) {
|
||||
BMessenger msg(NULL, ai.team);
|
||||
if (msg.IsValid()) {
|
||||
while (be_roster->IsRunning("application/x-vnd.Be-NETS")) {
|
||||
msg.SendMessage(B_QUIT_REQUESTED);
|
||||
snooze(500000);
|
||||
}
|
||||
}
|
||||
}
|
||||
BPath path;
|
||||
find_directory(B_BEOS_BOOT_DIRECTORY, &path);
|
||||
path.Append("Netscript");
|
||||
const char *argv[3] = {"/bin/sh", path.Path(), NULL};
|
||||
thread_id net_server = load_image(2, argv, (const char **)environ);
|
||||
resume_thread(net_server);
|
||||
status_t l;
|
||||
wait_for_thread(net_server, &l);
|
||||
goto i_wanna_try_that_again;
|
||||
}
|
||||
|
||||
// Set up communications with add-on
|
||||
area_id handler_buffer;
|
||||
if ((handler_buffer = find_area("packet buffer")) < B_NO_ERROR) {
|
||||
WarningAlert(GetString(STR_NET_ADDON_INIT_FAILED));
|
||||
return false;
|
||||
}
|
||||
if ((buffer_area = clone_area("local packet buffer", (void **)&net_buffer_ptr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, handler_buffer)) < B_NO_ERROR) {
|
||||
D(bug("EtherInit: couldn't clone packet area\n"));
|
||||
WarningAlert(GetString(STR_NET_ADDON_CLONE_FAILED));
|
||||
return false;
|
||||
}
|
||||
if ((read_sem = create_sem(0, "ether read")) < B_NO_ERROR) {
|
||||
printf("FATAL: can't create Ethernet semaphore\n");
|
||||
return false;
|
||||
}
|
||||
net_buffer_ptr->read_sem = read_sem;
|
||||
write_sem = net_buffer_ptr->write_sem;
|
||||
read_thread = spawn_thread(receive_proc, "Ethernet Receiver", B_URGENT_DISPLAY_PRIORITY, NULL);
|
||||
resume_thread(read_thread);
|
||||
for (int i=0; i<WRITE_PACKET_COUNT; i++)
|
||||
net_buffer_ptr->write[i].cmd = IN_USE | (ACTIVATE_SHEEP_NET << 8);
|
||||
rd_pos = wr_pos = 0;
|
||||
release_sem(write_sem);
|
||||
|
||||
// Get Ethernet address
|
||||
memcpy(ether_addr, net_buffer_ptr->ether_addr, 6);
|
||||
D(bug("Ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5]));
|
||||
|
||||
// Everything OK
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void ether_exit(void)
|
||||
{
|
||||
// Close communications with add-on
|
||||
for (int i=0; i<WRITE_PACKET_COUNT; i++)
|
||||
net_buffer_ptr->write[i].cmd = IN_USE | (DEACTIVATE_SHEEP_NET << 8);
|
||||
release_sem(write_sem);
|
||||
|
||||
// Quit reception thread
|
||||
ether_thread_active = false;
|
||||
status_t result;
|
||||
release_sem(read_sem);
|
||||
wait_for_thread(read_thread, &result);
|
||||
|
||||
delete_sem(read_sem);
|
||||
delete_area(buffer_area);
|
||||
|
||||
// Remove all protocols
|
||||
remove_all_protocols();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset
|
||||
*/
|
||||
|
||||
void ether_reset(void)
|
||||
{
|
||||
remove_all_protocols();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add multicast address
|
||||
*/
|
||||
|
||||
int16 ether_add_multicast(uint32 pb)
|
||||
{
|
||||
net_packet *p = &net_buffer_ptr->write[wr_pos];
|
||||
if (p->cmd & IN_USE) {
|
||||
D(bug("WARNING: Couldn't enable multicast address\n"));
|
||||
} else {
|
||||
Mac2Host_memcpy(p->data, pb + eMultiAddr, 6);
|
||||
p->length = 6;
|
||||
p->cmd = IN_USE | (ADD_MULTICAST << 8);
|
||||
wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
|
||||
release_sem(write_sem);
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete multicast address
|
||||
*/
|
||||
|
||||
int16 ether_del_multicast(uint32 pb)
|
||||
{
|
||||
net_packet *p = &net_buffer_ptr->write[wr_pos];
|
||||
if (p->cmd & IN_USE) {
|
||||
D(bug("WARNING: Couldn't enable multicast address\n"));
|
||||
} else {
|
||||
Mac2Host_memcpy(p->data, pb + eMultiAddr, 6);
|
||||
p->length = 6;
|
||||
p->cmd = IN_USE | (REMOVE_MULTICAST << 8);
|
||||
wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
|
||||
release_sem(write_sem);
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Attach protocol handler
|
||||
*/
|
||||
|
||||
int16 ether_attach_ph(uint16 type, uint32 handler)
|
||||
{
|
||||
// Already attached?
|
||||
NetProtocol *p = find_protocol(type);
|
||||
if (p != NULL)
|
||||
return lapProtErr;
|
||||
else {
|
||||
// No, create and attach
|
||||
p = new NetProtocol;
|
||||
p->type = type;
|
||||
p->handler = handler;
|
||||
prot_list.AddItem(p);
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Detach protocol handler
|
||||
*/
|
||||
|
||||
int16 ether_detach_ph(uint16 type)
|
||||
{
|
||||
NetProtocol *p = find_protocol(type);
|
||||
if (p != NULL) {
|
||||
prot_list.RemoveItem(p);
|
||||
delete p;
|
||||
return noErr;
|
||||
} else
|
||||
return lapProtErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transmit raw ethernet packet
|
||||
*/
|
||||
|
||||
int16 ether_write(uint32 wds)
|
||||
{
|
||||
net_packet *p = &net_buffer_ptr->write[wr_pos];
|
||||
if (p->cmd & IN_USE) {
|
||||
D(bug("WARNING: Couldn't transmit packet (buffer full)\n"));
|
||||
} else {
|
||||
|
||||
// Copy packet to buffer
|
||||
int len = ether_wds_to_buffer(wds, p->data);
|
||||
|
||||
#if MONITOR
|
||||
bug("Sending Ethernet packet:\n");
|
||||
for (int i=0; i<len; i++) {
|
||||
bug("%02x ", p->data[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
|
||||
// Notify add-on
|
||||
p->length = len;
|
||||
p->cmd = IN_USE | (SHEEP_PACKET << 8);
|
||||
wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
|
||||
release_sem(write_sem);
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Packet reception thread (non-UDP)
|
||||
*/
|
||||
|
||||
static status_t receive_proc(void *data)
|
||||
{
|
||||
while (ether_thread_active) {
|
||||
if (net_buffer_ptr->read[rd_pos].cmd & IN_USE) {
|
||||
D(bug(" packet received, triggering Ethernet interrupt\n"));
|
||||
SetInterruptFlag(INTFLAG_ETHER);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
acquire_sem_etc(read_sem, 1, B_TIMEOUT, 25000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Packet reception thread (UDP)
|
||||
*/
|
||||
|
||||
static status_t receive_proc_udp(void *data)
|
||||
{
|
||||
while (ether_thread_active) {
|
||||
fd_set readfds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0) {
|
||||
D(bug(" packet received, triggering Ethernet interrupt\n"));
|
||||
SetInterruptFlag(INTFLAG_ETHER);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Start UDP packet reception thread
|
||||
*/
|
||||
|
||||
bool ether_start_udp_thread(int socket_fd)
|
||||
{
|
||||
fd = socket_fd;
|
||||
udp_tunnel = true;
|
||||
ether_thread_active = true;
|
||||
read_thread = spawn_thread(receive_proc_udp, "UDP Receiver", B_URGENT_DISPLAY_PRIORITY, NULL);
|
||||
resume_thread(read_thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stop UDP packet reception thread
|
||||
*/
|
||||
|
||||
void ether_stop_udp_thread(void)
|
||||
{
|
||||
ether_thread_active = false;
|
||||
status_t result;
|
||||
wait_for_thread(read_thread, &result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ethernet interrupt - activate deferred tasks to call IODone or protocol handlers
|
||||
*/
|
||||
|
||||
void EtherInterrupt(void)
|
||||
{
|
||||
D(bug("EtherIRQ\n"));
|
||||
EthernetPacket ether_packet;
|
||||
uint32 packet = ether_packet.addr();
|
||||
|
||||
if (udp_tunnel) {
|
||||
|
||||
ssize_t length;
|
||||
|
||||
// Read packets from socket and hand to ether_udp_read() for processing
|
||||
while (true) {
|
||||
struct sockaddr_in from;
|
||||
socklen_t from_len = sizeof(from);
|
||||
length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len);
|
||||
if (length < 14)
|
||||
break;
|
||||
ether_udp_read(packet, length, &from);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Call protocol handler for received packets
|
||||
net_packet *p = &net_buffer_ptr->read[rd_pos];
|
||||
while (p->cmd & IN_USE) {
|
||||
if ((p->cmd >> 8) == SHEEP_PACKET) {
|
||||
Host2Mac_memcpy(packet, p->data, p->length);
|
||||
#if MONITOR
|
||||
bug("Receiving Ethernet packet:\n");
|
||||
for (int i=0; i<p->length; i++) {
|
||||
bug("%02x ", ReadMacInt8(packet + i));
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
// Get packet type
|
||||
uint16 type = ReadMacInt16(packet + 12);
|
||||
|
||||
// Look for protocol
|
||||
NetProtocol *prot = find_protocol(type);
|
||||
if (prot == NULL)
|
||||
goto next;
|
||||
|
||||
// No default handler
|
||||
if (prot->handler == 0)
|
||||
goto next;
|
||||
|
||||
// Copy header to RHA
|
||||
Mac2Mac_memcpy(ether_data + ed_RHA, packet, 14);
|
||||
D(bug(" header %08lx%04lx %08lx%04lx %04lx\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12)));
|
||||
|
||||
// Call protocol handler
|
||||
M68kRegisters r;
|
||||
r.d[0] = type; // Packet type
|
||||
r.d[1] = p->length - 14; // Remaining packet length (without header, for ReadPacket)
|
||||
r.a[0] = packet + 14; // Pointer to packet (Mac address, for ReadPacket)
|
||||
r.a[3] = ether_data + ed_RHA + 14; // Pointer behind header in RHA
|
||||
r.a[4] = ether_data + ed_ReadPacket; // Pointer to ReadPacket/ReadRest routines
|
||||
D(bug(" calling protocol handler %08lx, type %08lx, length %08lx, data %08lx, rha %08lx, read_packet %08lx\n", prot->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
|
||||
Execute68k(prot->handler, &r);
|
||||
}
|
||||
next: p->cmd = 0; // Free packet
|
||||
rd_pos = (rd_pos + 1) % READ_PACKET_COUNT;
|
||||
p = &net_buffer_ptr->read[rd_pos];
|
||||
}
|
||||
}
|
||||
D(bug(" EtherIRQ done\n"));
|
||||
}
|
|
@ -1,489 +0,0 @@
|
|||
/*
|
||||
* extfs_beos.cpp - MacOS file system for access native file system access, BeOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <fs_attr.h>
|
||||
#include <support/TypeConstants.h>
|
||||
#include <support/UTF8.h>
|
||||
#include <storage/Mime.h>
|
||||
|
||||
#include "extfs.h"
|
||||
#include "extfs_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Default Finder flags
|
||||
const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
|
||||
|
||||
// Temporary buffer for transfers from/to kernel space
|
||||
const int TMP_BUF_SIZE = 0x10000;
|
||||
static uint8 *tmp_buf = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void extfs_init(void)
|
||||
{
|
||||
// Allocate temporary buffer
|
||||
tmp_buf = new uint8[TMP_BUF_SIZE];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void extfs_exit(void)
|
||||
{
|
||||
// Delete temporary buffer
|
||||
delete[] tmp_buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add component to path name
|
||||
*/
|
||||
|
||||
void add_path_component(char *path, const char *component)
|
||||
{
|
||||
int l = strlen(path);
|
||||
if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
|
||||
path[l] = '/';
|
||||
path[l+1] = 0;
|
||||
}
|
||||
strncat(path, component, MAX_PATH_LENGTH-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get/set finder info for file/directory specified by full path
|
||||
*/
|
||||
|
||||
struct mime2type {
|
||||
const char *mime;
|
||||
uint32 type;
|
||||
uint32 creator;
|
||||
bool reversible; // type -> mime translation possible
|
||||
};
|
||||
|
||||
static const mime2type m2t_translation[] = {
|
||||
{"application/x-compress", 'ZIVM', 'LZIV', true},
|
||||
{"application/x-gzip", 'Gzip', 'Gzip', true},
|
||||
{"application/x-macbinary", 'BINA', '????', false},
|
||||
{"application/mac-binhex40", 'TEXT', 'SITx', false},
|
||||
{"application/pdf", 'PDF ', 'CARO', true},
|
||||
{"application/postscript", 'TEXT', 'ttxt', false},
|
||||
{"application/x-stuffit", 'SIT!', 'SITx', true},
|
||||
{"application/x-tar", 'TARF', 'TAR ', true},
|
||||
{"application/x-uuencode", 'TEXT', 'SITx', false},
|
||||
{"application/zip", 'ZIP ', 'ZIP ', true},
|
||||
{"audio/x-8svx", '8SVX', 'SNDM', true},
|
||||
{"audio/x-aifc", 'AIFC', 'TVOD', true},
|
||||
{"audio/x-aiff", 'AIFF', 'TVOD', true},
|
||||
{"audio/basic", 'ULAW', 'TVOD', true},
|
||||
{"audio/x-midi", 'MIDI', 'TVOD', true},
|
||||
{"audio/x-mpeg", 'MPG ', 'TVOD', true},
|
||||
{"audio/x-wav", 'WAVE', 'TVOD', true},
|
||||
{"image/x-bmp", 'BMPf', 'ogle', true},
|
||||
{"image/gif", 'GIFf', 'ogle', true},
|
||||
{"image/x-ilbm", 'ILBM', 'GKON', true},
|
||||
{"image/jpeg", 'JPEG', 'ogle', true},
|
||||
{"image/jpeg", 'JFIF', 'ogle', true},
|
||||
{"image/x-photoshop", '8BPS', '8BIM', true},
|
||||
{"image/pict", 'PICT', 'ogle', true},
|
||||
{"image/png", 'PNGf', 'ogle', true},
|
||||
{"image/x-sgi", '.SGI', 'ogle', true},
|
||||
{"image/x-targa", 'TPIC', 'ogle', true},
|
||||
{"image/tiff", 'TIFF', 'ogle', true},
|
||||
{"text/html", 'TEXT', 'MOSS', false},
|
||||
{"text/plain", 'TEXT', 'ttxt', true},
|
||||
{"text/rtf", 'TEXT', 'MSWD', false},
|
||||
{"text/x-source-code", 'TEXT', 'R*ch', false},
|
||||
{"video/mpeg", 'MPEG', 'TVOD', true},
|
||||
{"video/quicktime", 'MooV', 'TVOD', true},
|
||||
{"video/x-flc", 'FLI ', 'TVOD', true},
|
||||
{"video/x-msvideo", 'VfW ', 'TVOD', true},
|
||||
{NULL, 0, 0, false} // End marker
|
||||
};
|
||||
|
||||
void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
|
||||
{
|
||||
// Set default finder info
|
||||
Mac_memset(finfo, 0, SIZEOF_FInfo);
|
||||
if (fxinfo)
|
||||
Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
|
||||
WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
|
||||
WriteMacInt32(finfo + fdLocation, (uint32)-1);
|
||||
|
||||
// Open file
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
if (!is_dir) {
|
||||
|
||||
// Read BeOS MIME type
|
||||
ssize_t actual = fs_read_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, tmp_buf, 256);
|
||||
tmp_buf[255] = 0;
|
||||
|
||||
if (actual > 0) {
|
||||
|
||||
// Translate MIME type to MacOS type/creator
|
||||
uint8 mactype[4];
|
||||
if (sscanf((char *)tmp_buf, "application/x-MacOS-%c%c%c%c", mactype, mactype+1, mactype+2, mactype+3) == 4) {
|
||||
|
||||
// MacOS style type
|
||||
WriteMacInt32(finfo + fdType, (mactype[0] << 24) | (mactype[1] << 16) | (mactype[2] << 8) | mactype[3]);
|
||||
|
||||
} else {
|
||||
|
||||
// MIME string, look in table
|
||||
for (int i=0; m2t_translation[i].mime; i++) {
|
||||
if (!strcmp((char *)tmp_buf, m2t_translation[i].mime)) {
|
||||
WriteMacInt32(finfo + fdType, m2t_translation[i].type);
|
||||
WriteMacInt32(finfo + fdCreator, m2t_translation[i].creator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override file type with MACOS:CREATOR attribute
|
||||
if (fs_read_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4) == 4)
|
||||
WriteMacInt32(finfo + fdCreator, (tmp_buf[0] << 24) | (tmp_buf[1] << 16) | (tmp_buf[2] << 8) | tmp_buf[3]);
|
||||
}
|
||||
|
||||
// Read MACOS:HFS_FLAGS attribute
|
||||
if (fs_read_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2) == 2)
|
||||
WriteMacInt16(finfo + fdFlags, (tmp_buf[0] << 8) | tmp_buf[1]);
|
||||
|
||||
// Close file
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
|
||||
{
|
||||
// Open file
|
||||
int fd = open(path, O_WRONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
if (!is_dir) {
|
||||
|
||||
// Set BEOS:TYPE attribute
|
||||
uint32 type = ReadMacInt32(finfo + fdType);
|
||||
if (type) {
|
||||
for (int i=0; m2t_translation[i].mime; i++) {
|
||||
if (m2t_translation[i].type == type && m2t_translation[i].reversible) {
|
||||
fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, m2t_translation[i].mime, strlen(m2t_translation[i].mime) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set MACOS:CREATOR attribute
|
||||
uint32 creator = ReadMacInt32(finfo + fdCreator);
|
||||
if (creator) {
|
||||
tmp_buf[0] = creator >> 24;
|
||||
tmp_buf[1] = creator >> 16;
|
||||
tmp_buf[2] = creator >> 8;
|
||||
tmp_buf[3] = creator;
|
||||
fs_write_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4);
|
||||
}
|
||||
}
|
||||
|
||||
// Write MACOS:HFS_FLAGS attribute
|
||||
uint16 flags = ReadMacInt16(finfo + fdFlags);
|
||||
if (flags != DEFAULT_FINDER_FLAGS) {
|
||||
tmp_buf[0] = flags >> 8;
|
||||
tmp_buf[1] = flags;
|
||||
fs_write_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2);
|
||||
} else
|
||||
fs_remove_attr(fd, "MACOS:HFS_FLAGS");
|
||||
|
||||
// Close file
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resource fork emulation functions
|
||||
*/
|
||||
|
||||
uint32 get_rfork_size(const char *path)
|
||||
{
|
||||
// Open file
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
// Get size of MACOS:RFORK attribute
|
||||
struct attr_info info;
|
||||
if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
|
||||
info.size = 0;
|
||||
|
||||
// Close file and return size
|
||||
close(fd);
|
||||
return info.size;
|
||||
}
|
||||
|
||||
int open_rfork(const char *path, int flag)
|
||||
{
|
||||
// Open original file
|
||||
int fd = open(path, flag);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
// Open temporary file for resource fork
|
||||
char rname[L_tmpnam];
|
||||
tmpnam(rname);
|
||||
int rfd = open(rname, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
if (rfd < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
unlink(rname); // File will be deleted when closed
|
||||
|
||||
// Get size of MACOS:RFORK attribute
|
||||
struct attr_info info;
|
||||
if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
|
||||
info.size = 0;
|
||||
|
||||
// Copy resource data from attribute to temporary file
|
||||
if (info.size > 0) {
|
||||
|
||||
// Allocate buffer
|
||||
void *buf = malloc(info.size);
|
||||
if (buf == NULL) {
|
||||
close(rfd);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copy data
|
||||
fs_read_attr(fd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, info.size);
|
||||
write(rfd, buf, info.size);
|
||||
lseek(rfd, 0, SEEK_SET);
|
||||
|
||||
// Free buffer
|
||||
if (buf)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
// Close original file
|
||||
close(fd);
|
||||
return rfd;
|
||||
}
|
||||
|
||||
void close_rfork(const char *path, int fd)
|
||||
{
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
// Get size of temporary file
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0)
|
||||
st.st_size = 0;
|
||||
|
||||
// Open original file
|
||||
int ofd = open(path, O_WRONLY);
|
||||
if (ofd > 0) {
|
||||
|
||||
// Copy resource data to MACOS:RFORK attribute
|
||||
if (st.st_size > 0) {
|
||||
|
||||
// Allocate buffer
|
||||
void *buf = malloc(st.st_size);
|
||||
if (buf == NULL) {
|
||||
close(ofd);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy data
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
read(fd, buf, st.st_size);
|
||||
fs_write_attr(ofd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, st.st_size);
|
||||
|
||||
// Free buffer
|
||||
if (buf)
|
||||
free(buf);
|
||||
|
||||
} else
|
||||
fs_remove_attr(ofd, "MACOS:RFORK");
|
||||
|
||||
// Close original file
|
||||
close(ofd);
|
||||
}
|
||||
|
||||
// Close temporary file
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read "length" bytes from file to "buffer",
|
||||
* returns number of bytes read (or -1 on error)
|
||||
*/
|
||||
|
||||
static inline ssize_t sread(int fd, void *buf, size_t count)
|
||||
{
|
||||
ssize_t res;
|
||||
while ((res = read(fd, buf, count)) == B_INTERRUPTED) ;
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t extfs_read(int fd, void *buffer, size_t length)
|
||||
{
|
||||
// Buffer in kernel space?
|
||||
if ((uint32)buffer < 0x80000000) {
|
||||
|
||||
// Yes, transfer via buffer
|
||||
ssize_t actual = 0;
|
||||
while (length) {
|
||||
size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
|
||||
ssize_t res = sread(fd, tmp_buf, transfer_size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
memcpy(buffer, tmp_buf, res);
|
||||
buffer = (void *)((uint8 *)buffer + res);
|
||||
length -= res;
|
||||
actual += res;
|
||||
if (res != transfer_size)
|
||||
return actual;
|
||||
}
|
||||
return actual;
|
||||
|
||||
} else {
|
||||
|
||||
// No, transfer directly
|
||||
return sread(fd, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write "length" bytes from "buffer" to file,
|
||||
* returns number of bytes written (or -1 on error)
|
||||
*/
|
||||
|
||||
static inline ssize_t swrite(int fd, void *buf, size_t count)
|
||||
{
|
||||
ssize_t res;
|
||||
while ((res = write(fd, buf, count)) == B_INTERRUPTED) ;
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t extfs_write(int fd, void *buffer, size_t length)
|
||||
{
|
||||
// Buffer in kernel space?
|
||||
if ((uint32)buffer < 0x80000000) {
|
||||
|
||||
// Yes, transfer via buffer
|
||||
ssize_t actual = 0;
|
||||
while (length) {
|
||||
size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
|
||||
memcpy(tmp_buf, buffer, transfer_size);
|
||||
ssize_t res = swrite(fd, tmp_buf, transfer_size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
buffer = (void *)((uint8 *)buffer + res);
|
||||
length -= res;
|
||||
actual += res;
|
||||
if (res != transfer_size)
|
||||
return actual;
|
||||
}
|
||||
return actual;
|
||||
|
||||
} else {
|
||||
|
||||
// No, transfer directly
|
||||
return swrite(fd, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove file/directory, returns false on error (and sets errno)
|
||||
*/
|
||||
|
||||
bool extfs_remove(const char *path)
|
||||
{
|
||||
if (remove(path) < 0) {
|
||||
if (errno == EISDIR)
|
||||
return rmdir(path) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rename/move file/directory, returns false on error (and sets errno)
|
||||
*/
|
||||
|
||||
bool extfs_rename(const char *old_path, const char *new_path)
|
||||
{
|
||||
return rename(old_path, new_path) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strings (filenames) conversion
|
||||
*/
|
||||
|
||||
// Convert from the host OS filename encoding to MacRoman
|
||||
const char *host_encoding_to_macroman(const char *filename)
|
||||
{
|
||||
int32 state = 0;
|
||||
static char buffer[512];
|
||||
int32 size = sizeof(buffer) - 1;
|
||||
int32 insize = strlen(filename);
|
||||
convert_from_utf8(B_MAC_ROMAN_CONVERSION, filename, &insize, buffer, &size, &state);
|
||||
buffer[size] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Convert from MacRoman to host OS filename encoding
|
||||
const char *macroman_to_host_encoding(const char *filename)
|
||||
{
|
||||
int32 state = 0;
|
||||
static char buffer[512];
|
||||
int32 insize = strlen(filename);
|
||||
int32 size = sizeof(buffer) - 1;
|
||||
convert_to_utf8(B_MAC_ROMAN_CONVERSION, filename, &insize, buffer, &size, &state);
|
||||
buffer[size] = 0;
|
||||
return buffer;
|
||||
}
|
|
@ -1,826 +0,0 @@
|
|||
/*
|
||||
* main_beos.cpp - Startup code for BeOS
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <AppKit.h>
|
||||
#include <InterfaceKit.h>
|
||||
#include <KernelKit.h>
|
||||
#include <StorageKit.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "xpram.h"
|
||||
#include "timer.h"
|
||||
#include "video.h"
|
||||
#include "rom_patches.h"
|
||||
#include "prefs.h"
|
||||
#include "prefs_editor.h"
|
||||
#include "sys.h"
|
||||
#include "user_strings.h"
|
||||
#include "version.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "sheep_driver.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Constants
|
||||
const char APP_SIGNATURE[] = "application/x-vnd.cebix-BasiliskII";
|
||||
const char ROM_FILE_NAME[] = "ROM";
|
||||
const char RAM_AREA_NAME[] = "Macintosh RAM";
|
||||
const char ROM_AREA_NAME[] = "Macintosh ROM";
|
||||
const uint32 MSG_START = 'strt'; // Emulator start message
|
||||
const uint32 ROM_AREA_SIZE = 0x500000; // Enough to hold PowerMac ROM (for powerrom_cpu)
|
||||
|
||||
// Prototypes
|
||||
#if __POWERPC__
|
||||
static void sigsegv_handler(vregs *r);
|
||||
#endif
|
||||
|
||||
|
||||
// Application object
|
||||
class BasiliskII : public BApplication {
|
||||
public:
|
||||
BasiliskII() : BApplication(APP_SIGNATURE)
|
||||
{
|
||||
// Find application directory and cwd to it
|
||||
app_info the_info;
|
||||
GetAppInfo(&the_info);
|
||||
BEntry the_file(&the_info.ref);
|
||||
BEntry the_dir;
|
||||
the_file.GetParent(&the_dir);
|
||||
BPath the_path;
|
||||
the_dir.GetPath(&the_path);
|
||||
chdir(the_path.Path());
|
||||
|
||||
// Initialize other variables
|
||||
rom_area = ram_area = -1;
|
||||
xpram_thread = tick_thread = -1;
|
||||
xpram_thread_active = true;
|
||||
tick_thread_active = true;
|
||||
AllowQuitting = true;
|
||||
}
|
||||
virtual void ReadyToRun(void);
|
||||
virtual void MessageReceived(BMessage *msg);
|
||||
void StartEmulator(void);
|
||||
virtual bool QuitRequested(void);
|
||||
virtual void Quit(void);
|
||||
|
||||
thread_id xpram_thread; // XPRAM watchdog
|
||||
thread_id tick_thread; // 60Hz thread
|
||||
|
||||
volatile bool xpram_thread_active; // Flag for quitting the XPRAM thread
|
||||
volatile bool tick_thread_active; // Flag for quitting the 60Hz thread
|
||||
|
||||
bool AllowQuitting; // Flag: Alt-Q quitting allowed
|
||||
|
||||
private:
|
||||
static status_t emul_func(void *arg);
|
||||
static status_t tick_func(void *arg);
|
||||
static status_t xpram_func(void *arg);
|
||||
static void sigsegv_invoc(int sig, void *arg, vregs *r);
|
||||
|
||||
void init_rom(void);
|
||||
void load_rom(void);
|
||||
|
||||
area_id rom_area; // ROM area ID
|
||||
area_id ram_area; // RAM area ID
|
||||
|
||||
struct sigaction sigsegv_action; // Data access exception signal (of emulator thread)
|
||||
|
||||
// Exceptions
|
||||
class area_error {};
|
||||
class file_open_error {};
|
||||
class file_read_error {};
|
||||
class rom_size_error {};
|
||||
|
||||
char* vmdir;
|
||||
};
|
||||
|
||||
static BasiliskII *the_app;
|
||||
|
||||
|
||||
// CPU and FPU type, addressing mode
|
||||
int CPUType;
|
||||
bool CPUIs68060;
|
||||
int FPUType;
|
||||
bool TwentyFourBitAddressing;
|
||||
|
||||
|
||||
// Global variables for PowerROM CPU
|
||||
thread_id emul_thread = -1; // Emulator thread
|
||||
|
||||
#if __POWERPC__
|
||||
int sheep_fd = -1; // fd of sheep driver
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Create application object and start it
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
the_app = new BasiliskII();
|
||||
the_app->Run();
|
||||
delete the_app;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Run application
|
||||
*/
|
||||
|
||||
void BasiliskII::ReadyToRun(void)
|
||||
{
|
||||
// Initialize variables
|
||||
RAMBaseHost = NULL;
|
||||
ROMBaseHost = NULL;
|
||||
srand(real_time_clock());
|
||||
tzset();
|
||||
|
||||
// Print some info
|
||||
printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
|
||||
printf(" %s\n", GetString(STR_ABOUT_TEXT2));
|
||||
|
||||
// Delete old areas
|
||||
area_id old_ram_area = find_area(RAM_AREA_NAME);
|
||||
if (old_ram_area > 0)
|
||||
delete_area(old_ram_area);
|
||||
area_id old_rom_area = find_area(ROM_AREA_NAME);
|
||||
if (old_rom_area > 0)
|
||||
delete_area(old_rom_area);
|
||||
|
||||
// Read preferences
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
PrefsInit(vmdir, argc, argv);
|
||||
|
||||
// Init system routines
|
||||
SysInit();
|
||||
|
||||
// Show preferences editor (or start emulator directly)
|
||||
if (!PrefsFindBool("nogui"))
|
||||
PrefsEditor();
|
||||
else
|
||||
PostMessage(MSG_START);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Message received
|
||||
*/
|
||||
|
||||
void BasiliskII::MessageReceived(BMessage *msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case MSG_START:
|
||||
StartEmulator();
|
||||
break;
|
||||
default:
|
||||
BApplication::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Start emulator
|
||||
*/
|
||||
|
||||
void BasiliskII::StartEmulator(void)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
#if REAL_ADDRESSING
|
||||
// Open sheep driver and remap low memory
|
||||
sheep_fd = open("/dev/sheep", 0);
|
||||
if (sheep_fd < 0) {
|
||||
sprintf(str, GetString(STR_NO_SHEEP_DRIVER_ERR), strerror(sheep_fd), sheep_fd);
|
||||
ErrorAlert(str);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
}
|
||||
status_t res = ioctl(sheep_fd, SHEEP_UP);
|
||||
if (res < 0) {
|
||||
sprintf(str, GetString(STR_SHEEP_UP_ERR), strerror(res), res);
|
||||
ErrorAlert(str);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create area for Mac RAM
|
||||
RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
|
||||
if (RAMSize < 1024*1024) {
|
||||
WarningAlert(GetString(STR_SMALL_RAM_WARN));
|
||||
RAMSize = 1024*1024;
|
||||
}
|
||||
|
||||
RAMBaseHost = (uint8 *)0x10000000;
|
||||
ram_area = create_area(RAM_AREA_NAME, (void **)&RAMBaseHost, B_BASE_ADDRESS, RAMSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
if (ram_area < 0) {
|
||||
ErrorAlert(STR_NO_RAM_AREA_ERR);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
}
|
||||
D(bug("RAM area %ld at %p\n", ram_area, RAMBaseHost));
|
||||
|
||||
// Create area and load Mac ROM
|
||||
try {
|
||||
init_rom();
|
||||
} catch (area_error) {
|
||||
ErrorAlert(STR_NO_ROM_AREA_ERR);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
} catch (file_open_error) {
|
||||
ErrorAlert(STR_NO_ROM_FILE_ERR);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
} catch (file_read_error) {
|
||||
ErrorAlert(STR_ROM_FILE_READ_ERR);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
} catch (rom_size_error) {
|
||||
ErrorAlert(STR_ROM_SIZE_ERR);
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize everything
|
||||
if (!InitAll(NULL)) {
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write protect ROM
|
||||
set_area_protection(rom_area, B_READ_AREA);
|
||||
|
||||
// Disallow quitting with Alt-Q from now on
|
||||
AllowQuitting = false;
|
||||
|
||||
// Start XPRAM watchdog thread
|
||||
xpram_thread = spawn_thread(xpram_func, "XPRAM Watchdog", B_LOW_PRIORITY, this);
|
||||
resume_thread(xpram_thread);
|
||||
|
||||
// Start 60Hz interrupt
|
||||
tick_thread = spawn_thread(tick_func, "60Hz", B_REAL_TIME_PRIORITY, this);
|
||||
resume_thread(tick_thread);
|
||||
|
||||
// Start emulator thread
|
||||
emul_thread = spawn_thread(emul_func, "MacOS", B_NORMAL_PRIORITY, this);
|
||||
resume_thread(emul_thread);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Quit emulator
|
||||
*/
|
||||
|
||||
void QuitEmulator(void)
|
||||
{
|
||||
the_app->AllowQuitting = true;
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
exit_thread(0);
|
||||
}
|
||||
|
||||
bool BasiliskII::QuitRequested(void)
|
||||
{
|
||||
if (AllowQuitting)
|
||||
return BApplication::QuitRequested();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void BasiliskII::Quit(void)
|
||||
{
|
||||
status_t l;
|
||||
|
||||
// Stop 60Hz interrupt
|
||||
if (tick_thread > 0) {
|
||||
tick_thread_active = false;
|
||||
wait_for_thread(tick_thread, &l);
|
||||
}
|
||||
|
||||
// Wait for emulator thread to finish
|
||||
if (emul_thread > 0)
|
||||
wait_for_thread(emul_thread, &l);
|
||||
|
||||
// Exit 680x0 emulation
|
||||
Exit680x0();
|
||||
|
||||
// Stop XPRAM watchdog thread
|
||||
if (xpram_thread > 0) {
|
||||
xpram_thread_active = false;
|
||||
suspend_thread(xpram_thread); // Wake thread up from snooze()
|
||||
snooze(1000);
|
||||
resume_thread(xpram_thread);
|
||||
wait_for_thread(xpram_thread, &l);
|
||||
}
|
||||
|
||||
// Deinitialize everything
|
||||
ExitAll();
|
||||
|
||||
// Delete ROM area
|
||||
if (rom_area >= 0)
|
||||
delete_area(rom_area);
|
||||
|
||||
// Delete RAM area
|
||||
if (ram_area >= 0)
|
||||
delete_area(ram_area);
|
||||
|
||||
#if REAL_ADDRESSING
|
||||
// Unmap low memory and close memory mess driver
|
||||
if (sheep_fd >= 0) {
|
||||
ioctl(sheep_fd, SHEEP_DOWN);
|
||||
close(sheep_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Exit system routines
|
||||
SysExit();
|
||||
|
||||
// Exit preferences
|
||||
PrefsExit();
|
||||
|
||||
BApplication::Quit();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create area for ROM (sets rom_area) and load ROM file
|
||||
*
|
||||
* area_error : Cannot create area
|
||||
* file_open_error: Cannot open ROM file
|
||||
* file_read_error: Cannot read ROM file
|
||||
*/
|
||||
|
||||
void BasiliskII::init_rom(void)
|
||||
{
|
||||
// Create area for ROM
|
||||
ROMBaseHost = (uint8 *)0x40800000;
|
||||
rom_area = create_area(ROM_AREA_NAME, (void **)&ROMBaseHost, B_BASE_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
if (rom_area < 0)
|
||||
throw area_error();
|
||||
D(bug("ROM area %ld at %p\n", rom_area, ROMBaseHost));
|
||||
|
||||
// Load ROM
|
||||
load_rom();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load ROM file
|
||||
*
|
||||
* file_open_error: Cannot open ROM file
|
||||
* file_read_error: Cannot read ROM file
|
||||
*/
|
||||
|
||||
void BasiliskII::load_rom(void)
|
||||
{
|
||||
// Get rom file path from preferences
|
||||
const char *rom_path = PrefsFindString("rom");
|
||||
|
||||
// Try to open ROM file
|
||||
BFile file(rom_path ? rom_path : ROM_FILE_NAME, B_READ_ONLY);
|
||||
if (file.InitCheck() != B_NO_ERROR)
|
||||
throw file_open_error();
|
||||
|
||||
printf(GetString(STR_READING_ROM_FILE));
|
||||
|
||||
// Is the ROM size correct?
|
||||
off_t rom_size = 0;
|
||||
file.GetSize(&rom_size);
|
||||
if (rom_size != 64*1024 && rom_size != 128*1024 && rom_size != 256*1024 && rom_size != 512*1024 && rom_size != 1024*1024)
|
||||
throw rom_size_error();
|
||||
|
||||
uint8 *rom = new uint8[rom_size]; // Reading directly into the area doesn't work
|
||||
ssize_t actual = file.Read((void *)rom, rom_size);
|
||||
if (actual == rom_size)
|
||||
memcpy(ROMBaseHost, rom, rom_size);
|
||||
delete[] rom;
|
||||
if (actual != rom_size)
|
||||
throw file_read_error();
|
||||
ROMSize = rom_size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Emulator thread function
|
||||
*/
|
||||
|
||||
status_t BasiliskII::emul_func(void *arg)
|
||||
{
|
||||
BasiliskII *obj = (BasiliskII *)arg;
|
||||
|
||||
#if __POWERPC__
|
||||
// Install data access signal handler
|
||||
sigemptyset(&obj->sigsegv_action.sa_mask);
|
||||
obj->sigsegv_action.sa_handler = (__signal_func_ptr)(obj->sigsegv_invoc);
|
||||
obj->sigsegv_action.sa_flags = 0;
|
||||
obj->sigsegv_action.sa_userdata = arg;
|
||||
sigaction(SIGSEGV, &obj->sigsegv_action, NULL);
|
||||
#endif
|
||||
|
||||
// Exceptions will send signals
|
||||
disable_debugger(true);
|
||||
|
||||
// Start 68k and jump to ROM boot routine
|
||||
Start680x0();
|
||||
|
||||
// Quit program
|
||||
obj->AllowQuitting = true;
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Code was patched, flush caches if neccessary (i.e. when using a real 680x0
|
||||
* or a dynamically recompiling emulator)
|
||||
*/
|
||||
|
||||
void FlushCodeCache(void *start, uint32 size)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mutexes
|
||||
*/
|
||||
|
||||
struct B2_mutex {
|
||||
int dummy; //!!
|
||||
};
|
||||
|
||||
B2_mutex *B2_create_mutex(void)
|
||||
{
|
||||
return new B2_mutex;
|
||||
}
|
||||
|
||||
void B2_lock_mutex(B2_mutex *mutex)
|
||||
{
|
||||
}
|
||||
|
||||
void B2_unlock_mutex(B2_mutex *mutex)
|
||||
{
|
||||
}
|
||||
|
||||
void B2_delete_mutex(B2_mutex *mutex)
|
||||
{
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt flags (must be handled atomically!)
|
||||
*/
|
||||
|
||||
uint32 InterruptFlags = 0;
|
||||
|
||||
void SetInterruptFlag(uint32 flag)
|
||||
{
|
||||
atomic_or((int32 *)&InterruptFlags, flag);
|
||||
}
|
||||
|
||||
void ClearInterruptFlag(uint32 flag)
|
||||
{
|
||||
atomic_and((int32 *)&InterruptFlags, ~flag);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 60Hz thread (really 60.15Hz)
|
||||
*/
|
||||
|
||||
status_t BasiliskII::tick_func(void *arg)
|
||||
{
|
||||
BasiliskII *obj = (BasiliskII *)arg;
|
||||
int tick_counter = 0;
|
||||
bigtime_t current = system_time();
|
||||
|
||||
while (obj->tick_thread_active) {
|
||||
|
||||
// Wait
|
||||
current += 16625;
|
||||
snooze_until(current, B_SYSTEM_TIMEBASE);
|
||||
|
||||
// Pseudo Mac 1Hz interrupt, update local time
|
||||
if (++tick_counter > 60) {
|
||||
tick_counter = 0;
|
||||
WriteMacInt32(0x20c, TimerDateTime());
|
||||
SetInterruptFlag(INTFLAG_1HZ);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
|
||||
// Trigger 60Hz interrupt
|
||||
SetInterruptFlag(INTFLAG_60HZ);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XPRAM watchdog thread (saves XPRAM every minute)
|
||||
*/
|
||||
|
||||
status_t BasiliskII::xpram_func(void *arg)
|
||||
{
|
||||
uint8 last_xpram[XPRAM_SIZE];
|
||||
memcpy(last_xpram, XPRAM, XPRAM_SIZE);
|
||||
|
||||
while (((BasiliskII *)arg)->xpram_thread_active) {
|
||||
snooze(60*1000000);
|
||||
if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
|
||||
memcpy(last_xpram, XPRAM, XPRAM_SIZE);
|
||||
SaveXPRAM();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display error alert
|
||||
*/
|
||||
|
||||
void ErrorAlert(const char *text)
|
||||
{
|
||||
if (PrefsFindBool("nogui")) {
|
||||
printf(GetString(STR_SHELL_ERROR_PREFIX), text);
|
||||
return;
|
||||
}
|
||||
VideoQuitFullScreen();
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_GUI_ERROR_PREFIX), text);
|
||||
BAlert *alert = new BAlert(GetString(STR_ERROR_ALERT_TITLE), str, GetString(STR_QUIT_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
|
||||
alert->Go();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display warning alert
|
||||
*/
|
||||
|
||||
void WarningAlert(const char *text)
|
||||
{
|
||||
if (PrefsFindBool("nogui")) {
|
||||
printf(GetString(STR_SHELL_WARNING_PREFIX), text);
|
||||
return;
|
||||
}
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text);
|
||||
BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, GetString(STR_OK_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT);
|
||||
alert->Go();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display choice alert
|
||||
*/
|
||||
|
||||
bool ChoiceAlert(const char *text, const char *pos, const char *neg)
|
||||
{
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text);
|
||||
BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, pos, neg, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT);
|
||||
return alert->Go() == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SEGV handler
|
||||
*/
|
||||
|
||||
#if __POWERPC__
|
||||
static uint32 segv_r[32];
|
||||
|
||||
asm void BasiliskII::sigsegv_invoc(register int sig, register void *arg, register vregs *r)
|
||||
{
|
||||
mflr r0
|
||||
stw r0,8(r1)
|
||||
stwu r1,-56(r1)
|
||||
|
||||
lwz r3,segv_r(r2)
|
||||
stmw r13,13*4(r3)
|
||||
|
||||
mr r3,r5
|
||||
bl sigsegv_handler
|
||||
|
||||
lwz r3,segv_r(r2)
|
||||
lmw r13,13*4(r3)
|
||||
|
||||
lwz r0,56+8(r1)
|
||||
mtlr r0
|
||||
addi r1,r1,56
|
||||
blr
|
||||
}
|
||||
|
||||
static void sigsegv_handler(vregs *r)
|
||||
{
|
||||
// Fetch volatile registers
|
||||
segv_r[0] = r->r0;
|
||||
segv_r[1] = r->r1;
|
||||
segv_r[2] = r->r2;
|
||||
segv_r[3] = r->r3;
|
||||
segv_r[4] = r->r4;
|
||||
segv_r[5] = r->r5;
|
||||
segv_r[6] = r->r6;
|
||||
segv_r[7] = r->r7;
|
||||
segv_r[8] = r->r8;
|
||||
segv_r[9] = r->r9;
|
||||
segv_r[10] = r->r10;
|
||||
segv_r[11] = r->r11;
|
||||
segv_r[12] = r->r12;
|
||||
|
||||
// Get opcode and divide into fields
|
||||
uint32 opcode = *(uint32 *)r->pc;
|
||||
uint32 primop = opcode >> 26;
|
||||
uint32 exop = (opcode >> 1) & 0x3ff;
|
||||
uint32 ra = (opcode >> 16) & 0x1f;
|
||||
uint32 rb = (opcode >> 11) & 0x1f;
|
||||
uint32 rd = (opcode >> 21) & 0x1f;
|
||||
uint32 imm = opcode & 0xffff;
|
||||
|
||||
// Analyze opcode
|
||||
enum {
|
||||
TYPE_UNKNOWN,
|
||||
TYPE_LOAD,
|
||||
TYPE_STORE
|
||||
} transfer_type = TYPE_UNKNOWN;
|
||||
enum {
|
||||
SIZE_UNKNOWN,
|
||||
SIZE_BYTE,
|
||||
SIZE_HALFWORD,
|
||||
SIZE_WORD
|
||||
} transfer_size = SIZE_UNKNOWN;
|
||||
enum {
|
||||
MODE_UNKNOWN,
|
||||
MODE_NORM,
|
||||
MODE_U,
|
||||
MODE_X,
|
||||
MODE_UX
|
||||
} addr_mode = MODE_UNKNOWN;
|
||||
switch (primop) {
|
||||
case 31:
|
||||
switch (exop) {
|
||||
case 23: // lwzx
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
|
||||
case 55: // lwzux
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
|
||||
case 87: // lbzx
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
|
||||
case 119: // lbzux
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
|
||||
case 151: // stwx
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
|
||||
case 183: // stwux
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
|
||||
case 215: // stbx
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
|
||||
case 247: // stbux
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
|
||||
case 279: // lhzx
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
|
||||
case 311: // lhzux
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
|
||||
case 343: // lhax
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
|
||||
case 375: // lhaux
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
|
||||
case 407: // sthx
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
|
||||
case 439: // sthux
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 32: // lwz
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
|
||||
case 33: // lwzu
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
|
||||
case 34: // lbz
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
|
||||
case 35: // lbzu
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
|
||||
case 36: // stw
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
|
||||
case 37: // stwu
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
|
||||
case 38: // stb
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
|
||||
case 39: // stbu
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
|
||||
case 40: // lhz
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
|
||||
case 41: // lhzu
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
|
||||
case 42: // lha
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
|
||||
case 43: // lhau
|
||||
transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
|
||||
case 44: // sth
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
|
||||
case 45: // sthu
|
||||
transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
|
||||
}
|
||||
|
||||
// Calculate effective address
|
||||
uint32 addr = 0;
|
||||
switch (addr_mode) {
|
||||
case MODE_X:
|
||||
case MODE_UX:
|
||||
if (ra == 0)
|
||||
addr = segv_r[rb];
|
||||
else
|
||||
addr = segv_r[ra] + segv_r[rb];
|
||||
break;
|
||||
case MODE_NORM:
|
||||
case MODE_U:
|
||||
if (ra == 0)
|
||||
addr = (int32)(int16)imm;
|
||||
else
|
||||
addr = segv_r[ra] + (int32)(int16)imm;
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore ROM writes
|
||||
if (transfer_type == TYPE_STORE && addr >= (uint32)ROMBaseHost && addr < (uint32)ROMBaseHost + ROMSize) {
|
||||
// D(bug("WARNING: %s write access to ROM at %p, 68k pc %p\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->pc));
|
||||
if (addr_mode == MODE_U || addr_mode == MODE_UX)
|
||||
segv_r[ra] = addr;
|
||||
r->pc += 4;
|
||||
goto rti;
|
||||
}
|
||||
|
||||
// For all other errors, jump into debugger
|
||||
char str[256];
|
||||
sprintf(str, "SIGSEGV\n"
|
||||
" pc %08lx lr %08lx ctr %08lx msr %08lx\n"
|
||||
" xer %08lx cr %08lx fpscr %08lx\n"
|
||||
" r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
|
||||
" r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
|
||||
" r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
|
||||
" r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
|
||||
" r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
|
||||
" r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
|
||||
" r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
|
||||
" r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
|
||||
r->pc, r->lr, r->ctr, r->msr,
|
||||
r->xer, r->cr, r->fpscr,
|
||||
r->r0, r->r1, r->r2, r->r3,
|
||||
r->r4, r->r5, r->r6, r->r7,
|
||||
r->r8, r->r9, r->r10, r->r11,
|
||||
r->r12, segv_r[13], segv_r[14], segv_r[15],
|
||||
segv_r[16], segv_r[17], segv_r[18], segv_r[19],
|
||||
segv_r[20], segv_r[21], segv_r[22], segv_r[23],
|
||||
segv_r[24], segv_r[25], segv_r[26], segv_r[27],
|
||||
segv_r[28], segv_r[29], segv_r[30], segv_r[31]);
|
||||
disable_debugger(false);
|
||||
debugger(str);
|
||||
QuitEmulator();
|
||||
return;
|
||||
|
||||
rti:
|
||||
// Restore volatile registers
|
||||
r->r0 = segv_r[0];
|
||||
r->r1 = segv_r[1];
|
||||
r->r2 = segv_r[2];
|
||||
r->r3 = segv_r[3];
|
||||
r->r4 = segv_r[4];
|
||||
r->r5 = segv_r[5];
|
||||
r->r6 = segv_r[6];
|
||||
r->r7 = segv_r[7];
|
||||
r->r8 = segv_r[8];
|
||||
r->r9 = segv_r[9];
|
||||
r->r10 = segv_r[10];
|
||||
r->r11 = segv_r[11];
|
||||
r->r12 = segv_r[12];
|
||||
}
|
||||
#endif
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* prefs_beos.cpp - Preferences handling, BeOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <StorageKit.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "prefs.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
// Platform-specific preferences items
|
||||
prefs_desc platform_prefs_items[] = {
|
||||
{"powerrom", TYPE_STRING, false, "path of PowerMac ROM"},
|
||||
{NULL, TYPE_END, false, NULL} // End of list
|
||||
};
|
||||
|
||||
|
||||
// Preferences file name and path
|
||||
const char PREFS_FILE_NAME[] = "BasiliskII_prefs";
|
||||
static BPath prefs_path;
|
||||
|
||||
|
||||
/*
|
||||
* Load preferences from settings file
|
||||
*/
|
||||
|
||||
void LoadPrefs(const char* vmdir)
|
||||
{
|
||||
#if 0
|
||||
if (vmdir) {
|
||||
prefs_path.SetTo(vmdir);
|
||||
prefs_path.Append("prefs");
|
||||
FILE *prefs = fopen(prefs_path.Path(), "r");
|
||||
if (!prefs) {
|
||||
printf("No file at %s found.\n", prefs_path.Path());
|
||||
exit(1);
|
||||
}
|
||||
LoadPrefsFromStream(prefs);
|
||||
fclose(prefs);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Construct prefs path
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, &prefs_path, true);
|
||||
prefs_path.Append(PREFS_FILE_NAME);
|
||||
|
||||
// Read preferences from settings file
|
||||
FILE *f = fopen(prefs_path.Path(), "r");
|
||||
if (f != NULL) {
|
||||
|
||||
// Prefs file found, load settings
|
||||
LoadPrefsFromStream(f);
|
||||
fclose(f);
|
||||
|
||||
} else {
|
||||
|
||||
// No prefs file, save defaults
|
||||
SavePrefs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save preferences to settings file
|
||||
*/
|
||||
|
||||
void SavePrefs(void)
|
||||
{
|
||||
FILE *f;
|
||||
if ((f = fopen(prefs_path.Path(), "w")) != NULL) {
|
||||
SavePrefsToStream(f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add defaults of platform-specific prefs items
|
||||
* You may also override the defaults set in PrefsInit()
|
||||
*/
|
||||
|
||||
void AddPlatformPrefsDefaults(void)
|
||||
{
|
||||
PrefsReplaceString("extfs", "/boot");
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,237 +0,0 @@
|
|||
/*
|
||||
* scsi_beos.cpp - SCSI Manager, BeOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <device/scsi.h>
|
||||
#ifdef __HAIKU__
|
||||
#include <CAM.h>
|
||||
#else
|
||||
#include <drivers/CAM.h>
|
||||
#endif
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "scsi.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Global variables
|
||||
static raw_device_command rdc;
|
||||
|
||||
static int fds[8*8]; // fd's for 8 units and 8 LUNs each
|
||||
static int fd; // Active fd (selected target)
|
||||
|
||||
static uint32 buffer_size; // Size of data buffer
|
||||
static uint8 *buffer = NULL; // Pointer to data buffer
|
||||
|
||||
static uint8 sense_data[256]; // Buffer for autosense data
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void SCSIInit(void)
|
||||
{
|
||||
int id, lun;
|
||||
|
||||
// Allocate buffer
|
||||
buffer = (uint8 *)malloc(buffer_size = 0x10000);
|
||||
|
||||
// Open scsi_raw driver for all 8 units (and all 8 LUNs)
|
||||
char dev_name[256];
|
||||
for (id=0; id<8; id++) {
|
||||
for (lun=0; lun<8; lun++)
|
||||
fds[id*8+lun] = -1;
|
||||
char prefs_name[16];
|
||||
sprintf(prefs_name, "scsi%d", id);
|
||||
const char *str = PrefsFindString(prefs_name);
|
||||
if (str) {
|
||||
int bus, unit;
|
||||
if (sscanf(str, "%d/%d", &bus, &unit) == 2) {
|
||||
for (lun=0; lun<8; lun++) {
|
||||
sprintf(dev_name, "/dev/bus/scsi/%d/%d/%d/raw", bus, unit, lun);
|
||||
D(bug("SCSI %d: Opening %s\n", id, dev_name));
|
||||
fds[id*8+lun] = open(dev_name, O_RDWR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset SCSI bus
|
||||
SCSIReset();
|
||||
|
||||
// Init rdc
|
||||
memset(&rdc, 0, sizeof(rdc));
|
||||
rdc.data = buffer;
|
||||
rdc.sense_data = sense_data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void SCSIExit(void)
|
||||
{
|
||||
// Close all devices
|
||||
for (int i=0; i<8; i++)
|
||||
for (int j=0; j<8; j++) {
|
||||
int fd = fds[i*8+j];
|
||||
if (fd > 0)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
// Free buffer
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if requested data size fits into buffer, allocate new buffer if needed
|
||||
*/
|
||||
|
||||
static bool try_buffer(int size)
|
||||
{
|
||||
if (size <= buffer_size)
|
||||
return true;
|
||||
|
||||
uint8 *new_buffer = (uint8 *)malloc(size);
|
||||
if (new_buffer == NULL)
|
||||
return false;
|
||||
free(buffer);
|
||||
buffer = new_buffer;
|
||||
buffer_size = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set SCSI command to be sent by scsi_send_cmd()
|
||||
*/
|
||||
|
||||
void scsi_set_cmd(int cmd_length, uint8 *cmd)
|
||||
{
|
||||
rdc.command_length = cmd_length;
|
||||
memcpy(rdc.command, cmd, cmd_length);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for presence of SCSI target
|
||||
*/
|
||||
|
||||
bool scsi_is_target_present(int id)
|
||||
{
|
||||
return fds[id * 8] > 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set SCSI target (returns false on error)
|
||||
*/
|
||||
|
||||
bool scsi_set_target(int id, int lun)
|
||||
{
|
||||
int new_fd = fds[id * 8 + lun];
|
||||
if (new_fd < 0)
|
||||
return false;
|
||||
if (new_fd != fd)
|
||||
rdc.cam_status &= ~CAM_AUTOSNS_VALID; // Clear sense data when selecting new target
|
||||
fd = new_fd;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send SCSI command to active target (scsi_set_command() must have been called),
|
||||
* read/write data according to S/G table (returns false on error); timeout is in 1/60 sec
|
||||
*/
|
||||
|
||||
bool scsi_send_cmd(size_t data_length, bool reading, int sg_size, uint8 **sg_ptr, uint32 *sg_len, uint16 *stat, uint32 timeout)
|
||||
{
|
||||
// Check if buffer is large enough, allocate new buffer if needed
|
||||
if (!try_buffer(data_length)) {
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_SCSI_BUFFER_ERR), data_length);
|
||||
ErrorAlert(str);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process S/G table when writing
|
||||
if (!reading) {
|
||||
D(bug(" writing to buffer\n"));
|
||||
uint8 *buffer_ptr = buffer;
|
||||
for (int i=0; i<sg_size; i++) {
|
||||
uint32 len = sg_len[i];
|
||||
D(bug(" %d bytes from %08lx\n", len, sg_ptr[i]));
|
||||
memcpy(buffer_ptr, sg_ptr[i], len);
|
||||
buffer_ptr += len;
|
||||
}
|
||||
}
|
||||
|
||||
// Request Sense and autosense data valid?
|
||||
status_t res = B_NO_ERROR;
|
||||
if (rdc.command[0] == 0x03 && (rdc.cam_status & CAM_AUTOSNS_VALID)) {
|
||||
|
||||
// Yes, fake command
|
||||
D(bug(" autosense\n"));
|
||||
memcpy(buffer, sense_data, 256 - rdc.sense_data_length);
|
||||
rdc.scsi_status = 0;
|
||||
rdc.cam_status = CAM_REQ_CMP;
|
||||
|
||||
} else {
|
||||
|
||||
// No, send regular command
|
||||
D(bug(" sending command, length %d\n", data_length));
|
||||
rdc.flags = (reading ? B_RAW_DEVICE_DATA_IN : 0) | B_RAW_DEVICE_REPORT_RESIDUAL | B_RAW_DEVICE_SHORT_READ_VALID;
|
||||
rdc.data_length = data_length;
|
||||
rdc.sense_data_length = 256;
|
||||
rdc.scsi_status = 0;
|
||||
rdc.cam_status = CAM_REQ_CMP;
|
||||
rdc.timeout = timeout * 16667;
|
||||
res = ioctl(fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc));
|
||||
D(bug(" command sent, res %08x, status %d, cam_status %02x\n", res, rdc.scsi_status, rdc.cam_status));
|
||||
*stat = rdc.scsi_status;
|
||||
}
|
||||
|
||||
// Process S/G table when reading
|
||||
if (reading && rdc.cam_status == CAM_REQ_CMP) {
|
||||
D(bug(" reading from buffer\n"));
|
||||
uint8 *buffer_ptr = buffer;
|
||||
for (int i=0; i<sg_size; i++) {
|
||||
uint32 len = sg_len[i];
|
||||
D(bug(" %d bytes to %08lx\n", len, sg_ptr[i]));
|
||||
memcpy(sg_ptr[i], buffer_ptr, len);
|
||||
buffer_ptr += len;
|
||||
}
|
||||
}
|
||||
return res ? false : true;
|
||||
}
|
|
@ -1,873 +0,0 @@
|
|||
/*
|
||||
* serial_beos.cpp - Serial device driver, BeOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <DeviceKit.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "macos_util.h"
|
||||
#include "prefs.h"
|
||||
#include "serial.h"
|
||||
#include "serial_defs.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define MONITOR 0
|
||||
|
||||
|
||||
// Buffer size for kernel-space transfers
|
||||
const int TMP_BUF_SIZE = 2048;
|
||||
|
||||
// These packets are sent to the input/output threads
|
||||
const uint32 CMD_READ = 'read';
|
||||
const uint32 CMD_WRITE = 'writ';
|
||||
const uint32 CMD_QUIT = 'quit';
|
||||
|
||||
struct ThreadPacket {
|
||||
uint32 pb;
|
||||
};
|
||||
|
||||
|
||||
// Driver private variables
|
||||
class BeSERDPort : public SERDPort {
|
||||
public:
|
||||
BeSERDPort(const char *dev)
|
||||
{
|
||||
device_name = dev;
|
||||
if (strstr(dev, "parallel")) {
|
||||
is_parallel = true;
|
||||
fd = -1;
|
||||
device = NULL;
|
||||
} else {
|
||||
is_parallel = false;
|
||||
device = new BSerialPort;
|
||||
}
|
||||
device_sem = create_sem(1, "serial port");
|
||||
input_thread = output_thread = 0;
|
||||
}
|
||||
|
||||
virtual ~BeSERDPort()
|
||||
{
|
||||
status_t l;
|
||||
if (input_thread > 0) {
|
||||
send_data(input_thread, CMD_QUIT, NULL, 0);
|
||||
suspend_thread(input_thread); // Unblock thread
|
||||
snooze(1000);
|
||||
resume_thread(input_thread);
|
||||
while (wait_for_thread(input_thread, &l) == B_INTERRUPTED) ;
|
||||
}
|
||||
if (output_thread > 0) {
|
||||
send_data(output_thread, CMD_QUIT, NULL, 0);
|
||||
suspend_thread(output_thread); // Unblock thread
|
||||
snooze(1000);
|
||||
resume_thread(output_thread);
|
||||
while (wait_for_thread(output_thread, &l) == B_INTERRUPTED) ;
|
||||
}
|
||||
acquire_sem(device_sem);
|
||||
delete_sem(device_sem);
|
||||
delete device;
|
||||
}
|
||||
|
||||
virtual int16 open(uint16 config);
|
||||
virtual int16 prime_in(uint32 pb, uint32 dce);
|
||||
virtual int16 prime_out(uint32 pb, uint32 dce);
|
||||
virtual int16 control(uint32 pb, uint32 dce, uint16 code);
|
||||
virtual int16 status(uint32 pb, uint32 dce, uint16 code);
|
||||
virtual int16 close(void);
|
||||
|
||||
private:
|
||||
bool configure(uint16 config);
|
||||
void set_handshake(uint32 s, bool with_dtr);
|
||||
static status_t input_func(void *arg);
|
||||
static status_t output_func(void *arg);
|
||||
|
||||
const char *device_name; // Name of BeOS port
|
||||
BSerialPort *device; // BeOS port object
|
||||
bool is_parallel; // Flag: Port is parallel, use fd
|
||||
int fd; // FD for parallel ports
|
||||
sem_id device_sem; // BSerialPort arbitration
|
||||
|
||||
thread_id input_thread; // Data input thread
|
||||
thread_id output_thread; // Data output thread
|
||||
|
||||
bool io_killed; // Flag: KillIO called, I/O threads must not call deferred tasks
|
||||
bool drop_dtr_on_close; // Flag: Negate DTR when driver is closed
|
||||
|
||||
uint8 tmp_in_buf[TMP_BUF_SIZE]; // Buffers for copying from/to kernel space
|
||||
uint8 tmp_out_buf[TMP_BUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
#if DEBUG
|
||||
static const int baud_rates[] = {
|
||||
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 31250
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void SerialInit(void)
|
||||
{
|
||||
// Read serial preferences and create structs for both ports
|
||||
the_serd_port[0] = new BeSERDPort(PrefsFindString("seriala"));
|
||||
the_serd_port[1] = new BeSERDPort(PrefsFindString("serialb"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void SerialExit(void)
|
||||
{
|
||||
delete (BeSERDPort *)the_serd_port[0];
|
||||
delete (BeSERDPort *)the_serd_port[1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open serial port
|
||||
*/
|
||||
|
||||
int16 BeSERDPort::open(uint16 config)
|
||||
{
|
||||
// Don't open NULL name devices
|
||||
if (device_name == NULL)
|
||||
return openErr;
|
||||
|
||||
// Init variables
|
||||
io_killed = false;
|
||||
drop_dtr_on_close = true;
|
||||
|
||||
// Open port
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
if (is_parallel) {
|
||||
char name[256];
|
||||
sprintf(name, "/dev/parallel/%s", device_name);
|
||||
fd = ::open(name, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
release_sem(device_sem);
|
||||
return openErr;
|
||||
}
|
||||
} else {
|
||||
device->SetFlowControl(B_HARDWARE_CONTROL); // Must be set before port is opened
|
||||
if (device->Open(device_name) > 0) {
|
||||
device->SetBlocking(true);
|
||||
device->SetTimeout(10000000);
|
||||
device->SetDTR(true);
|
||||
device->SetRTS(true);
|
||||
} else {
|
||||
release_sem(device_sem);
|
||||
return openErr;
|
||||
}
|
||||
}
|
||||
|
||||
// Start input/output threads
|
||||
release_sem(device_sem);
|
||||
configure(config);
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
while ((input_thread = spawn_thread(input_func, "Serial Input", B_NORMAL_PRIORITY, this)) == B_INTERRUPTED) ;
|
||||
resume_thread(input_thread);
|
||||
while ((output_thread = spawn_thread(output_func, "Serial Output", B_NORMAL_PRIORITY, this)) == B_INTERRUPTED) ;
|
||||
resume_thread(output_thread);
|
||||
release_sem(device_sem);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read data from port
|
||||
*/
|
||||
|
||||
int16 BeSERDPort::prime_in(uint32 pb, uint32 dce)
|
||||
{
|
||||
// Send input command to input_thread
|
||||
read_done = false;
|
||||
read_pending = true;
|
||||
ThreadPacket p;
|
||||
p.pb = pb;
|
||||
WriteMacInt32(input_dt + serdtDCE, dce);
|
||||
while (send_data(input_thread, CMD_READ, &p, sizeof(ThreadPacket)) == B_INTERRUPTED) ;
|
||||
return 1; // Command in progress
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write data to port
|
||||
*/
|
||||
|
||||
int16 BeSERDPort::prime_out(uint32 pb, uint32 dce)
|
||||
{
|
||||
// Send output command to output_thread
|
||||
write_done = false;
|
||||
write_pending = true;
|
||||
ThreadPacket p;
|
||||
p.pb = pb;
|
||||
WriteMacInt32(output_dt + serdtDCE, dce);
|
||||
while (send_data(output_thread, CMD_WRITE, &p, sizeof(ThreadPacket)) == B_INTERRUPTED) ;
|
||||
return 1; // Command in progress
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Control calls
|
||||
*/
|
||||
|
||||
int16 BeSERDPort::control(uint32 pb, uint32 dce, uint16 code)
|
||||
{
|
||||
switch (code) {
|
||||
case 1: // KillIO
|
||||
io_killed = true;
|
||||
suspend_thread(input_thread); // Unblock threads
|
||||
suspend_thread(output_thread);
|
||||
snooze(1000);
|
||||
resume_thread(input_thread);
|
||||
resume_thread(output_thread);
|
||||
while (read_pending || write_pending)
|
||||
snooze(10000);
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->ClearInput();
|
||||
device->ClearOutput();
|
||||
release_sem(device_sem);
|
||||
}
|
||||
io_killed = false;
|
||||
return noErr;
|
||||
|
||||
case kSERDConfiguration:
|
||||
if (configure(ReadMacInt16(pb + csParam)))
|
||||
return noErr;
|
||||
else
|
||||
return paramErr;
|
||||
|
||||
case kSERDInputBuffer:
|
||||
return noErr; // Not supported under BeOS
|
||||
|
||||
case kSERDSerHShake:
|
||||
set_handshake(pb + csParam, false);
|
||||
return noErr;
|
||||
|
||||
case kSERDClearBreak:
|
||||
case kSERDSetBreak:
|
||||
return noErr; // Not supported under BeOS
|
||||
|
||||
case kSERDBaudRate:
|
||||
if (!is_parallel) {
|
||||
uint16 rate = ReadMacInt16(pb + csParam);
|
||||
data_rate baud_rate;
|
||||
if (rate <= 50) {
|
||||
rate = 50; baud_rate = B_50_BPS;
|
||||
} else if (rate <= 75) {
|
||||
rate = 75; baud_rate = B_75_BPS;
|
||||
} else if (rate <= 110) {
|
||||
rate = 110; baud_rate = B_110_BPS;
|
||||
} else if (rate <= 134) {
|
||||
rate = 134; baud_rate = B_134_BPS;
|
||||
} else if (rate <= 150) {
|
||||
rate = 150; baud_rate = B_150_BPS;
|
||||
} else if (rate <= 200) {
|
||||
rate = 200; baud_rate = B_200_BPS;
|
||||
} else if (rate <= 300) {
|
||||
rate = 300; baud_rate = B_300_BPS;
|
||||
} else if (rate <= 600) {
|
||||
rate = 600; baud_rate = B_600_BPS;
|
||||
} else if (rate <= 1200) {
|
||||
rate = 1200; baud_rate = B_1200_BPS;
|
||||
} else if (rate <= 1800) {
|
||||
rate = 1800; baud_rate = B_1800_BPS;
|
||||
} else if (rate <= 2400) {
|
||||
rate = 2400; baud_rate = B_2400_BPS;
|
||||
} else if (rate <= 4800) {
|
||||
rate = 4800; baud_rate = B_4800_BPS;
|
||||
} else if (rate <= 9600) {
|
||||
rate = 9600; baud_rate = B_9600_BPS;
|
||||
} else if (rate <= 19200) {
|
||||
rate = 19200; baud_rate = B_19200_BPS;
|
||||
} else if (rate <= 31250) {
|
||||
rate = 31250; baud_rate = B_31250_BPS;
|
||||
} else if (rate <= 38400) {
|
||||
rate = 38400; baud_rate = B_38400_BPS;
|
||||
} else if (rate <= 57600) {
|
||||
rate = 57600; baud_rate = B_57600_BPS;
|
||||
}
|
||||
WriteMacInt16(pb + csParam, rate);
|
||||
acquire_sem(device_sem);
|
||||
if (device->SetDataRate(baud_rate) == B_OK) {
|
||||
release_sem(device_sem);
|
||||
return noErr;
|
||||
} else {
|
||||
release_sem(device_sem);
|
||||
return paramErr;
|
||||
}
|
||||
} else
|
||||
return noErr;
|
||||
|
||||
case kSERDHandshake:
|
||||
case kSERDHandshakeRS232:
|
||||
set_handshake(pb + csParam, true);
|
||||
return noErr;
|
||||
|
||||
case kSERDClockMIDI:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->SetParityMode(B_NO_PARITY);
|
||||
device->SetDataBits(B_DATA_BITS_8);
|
||||
device->SetStopBits(B_STOP_BITS_1);
|
||||
if (device->SetDataRate(B_31250_BPS) == B_OK) {
|
||||
release_sem(device_sem);
|
||||
return noErr;
|
||||
} else {
|
||||
release_sem(device_sem);
|
||||
return paramErr;
|
||||
}
|
||||
} else
|
||||
return noErr;
|
||||
|
||||
case kSERDMiscOptions:
|
||||
drop_dtr_on_close = !(ReadMacInt8(pb + csParam) & kOptionPreserveDTR);
|
||||
return noErr;
|
||||
|
||||
case kSERDAssertDTR:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->SetDTR(true);
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERDNegateDTR:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->SetDTR(false);
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERDSetPEChar:
|
||||
case kSERDSetPEAltChar:
|
||||
return noErr; // Not supported under BeOS
|
||||
|
||||
case kSERDResetChannel:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->ClearInput();
|
||||
device->ClearOutput();
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERDAssertRTS:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->SetRTS(true);
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERDNegateRTS:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->SetRTS(false);
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERD115KBaud:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
if (device->DataRate() != B_115200_BPS)
|
||||
if (device->SetDataRate(B_115200_BPS) != B_OK) {
|
||||
release_sem(device_sem);
|
||||
return paramErr;
|
||||
}
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERD230KBaud:
|
||||
case kSERDSetHighSpeed:
|
||||
if (!is_parallel) {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
if (device->DataRate() != B_230400_BPS)
|
||||
if (device->SetDataRate(B_230400_BPS) != B_OK) {
|
||||
release_sem(device_sem);
|
||||
return paramErr;
|
||||
}
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
default:
|
||||
printf("WARNING: SerialControl(): unimplemented control code %d\n", code);
|
||||
return controlErr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Status calls
|
||||
*/
|
||||
|
||||
int16 BeSERDPort::status(uint32 pb, uint32 dce, uint16 code)
|
||||
{
|
||||
switch (code) {
|
||||
case kSERDInputCount:
|
||||
WriteMacInt32(pb + csParam, 0);
|
||||
if (!is_parallel) {
|
||||
int32 num = 0;
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
device->NumCharsAvailable(&num);
|
||||
release_sem(device_sem);
|
||||
D(bug(" %d bytes in buffer\n", num));
|
||||
WriteMacInt32(pb + csParam, num);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
case kSERDStatus: {
|
||||
uint32 p = pb + csParam;
|
||||
WriteMacInt8(p + staCumErrs, cum_errors);
|
||||
cum_errors = 0;
|
||||
WriteMacInt8(p + staXOffSent, 0);
|
||||
WriteMacInt8(p + staXOffHold, 0);
|
||||
WriteMacInt8(p + staRdPend, read_pending);
|
||||
WriteMacInt8(p + staWrPend, write_pending);
|
||||
if (is_parallel) {
|
||||
WriteMacInt8(p + staCtsHold, 0);
|
||||
WriteMacInt8(p + staDsrHold, 0);
|
||||
WriteMacInt8(p + staModemStatus, dsrEvent | dcdEvent | ctsEvent);
|
||||
} else {
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
WriteMacInt8(p + staCtsHold, !device->IsCTS());
|
||||
WriteMacInt8(p + staDsrHold, !device->IsDSR());
|
||||
WriteMacInt8(p + staModemStatus,
|
||||
(device->IsDSR() ? dsrEvent : 0)
|
||||
| (device->IsRI() ? riEvent : 0)
|
||||
| (device->IsDCD() ? dcdEvent : 0)
|
||||
| (device->IsCTS() ? ctsEvent : 0));
|
||||
release_sem(device_sem);
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("WARNING: SerialStatus(): unimplemented status code %d\n", code);
|
||||
return statusErr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close serial port
|
||||
*/
|
||||
|
||||
int16 BeSERDPort::close()
|
||||
{
|
||||
// Kill threads
|
||||
status_t l;
|
||||
io_killed = true;
|
||||
if (input_thread > 0) {
|
||||
while (send_data(input_thread, CMD_QUIT, NULL, 0) == B_INTERRUPTED) ;
|
||||
if (read_pending) {
|
||||
suspend_thread(input_thread); // Unblock thread
|
||||
snooze(1000);
|
||||
resume_thread(input_thread);
|
||||
}
|
||||
while (wait_for_thread(input_thread, &l) == B_INTERRUPTED) ;
|
||||
}
|
||||
if (output_thread > 0) {
|
||||
while (send_data(output_thread, CMD_QUIT, NULL, 0) == B_INTERRUPTED) ;
|
||||
if (write_pending) {
|
||||
suspend_thread(output_thread); // Unblock thread
|
||||
snooze(1000);
|
||||
resume_thread(output_thread);
|
||||
}
|
||||
while (wait_for_thread(output_thread, &l) == B_INTERRUPTED) ;
|
||||
}
|
||||
input_thread = output_thread = 0;
|
||||
|
||||
// Close port
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
if (is_parallel) {
|
||||
::close(fd);
|
||||
fd = -1;
|
||||
} else {
|
||||
if (drop_dtr_on_close)
|
||||
device->SetDTR(false);
|
||||
device->Close();
|
||||
}
|
||||
release_sem(device_sem);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Configure serial port with MacOS config word
|
||||
*/
|
||||
|
||||
bool BeSERDPort::configure(uint16 config)
|
||||
{
|
||||
D(bug(" configure %04x\n", config));
|
||||
if (is_parallel)
|
||||
return true;
|
||||
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
|
||||
// Set number of stop bits
|
||||
switch (config & 0xc000) {
|
||||
case stop10:
|
||||
if (device->StopBits() != B_STOP_BITS_1)
|
||||
device->SetStopBits(B_STOP_BITS_1);
|
||||
break;
|
||||
case stop20:
|
||||
if (device->StopBits() != B_STOP_BITS_2)
|
||||
device->SetStopBits(B_STOP_BITS_2);
|
||||
break;
|
||||
default:
|
||||
release_sem(device_sem);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set parity mode
|
||||
switch (config & 0x3000) {
|
||||
case noParity:
|
||||
if (device->ParityMode() != B_NO_PARITY)
|
||||
device->SetParityMode(B_NO_PARITY);
|
||||
break;
|
||||
case oddParity:
|
||||
if (device->ParityMode() != B_ODD_PARITY)
|
||||
device->SetParityMode(B_ODD_PARITY);
|
||||
break;
|
||||
case evenParity:
|
||||
if (device->ParityMode() != B_EVEN_PARITY)
|
||||
device->SetParityMode(B_EVEN_PARITY);
|
||||
break;
|
||||
default:
|
||||
release_sem(device_sem);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set number of data bits
|
||||
switch (config & 0x0c00) {
|
||||
case data7:
|
||||
if (device->DataBits() != B_DATA_BITS_7)
|
||||
device->SetDataBits(B_DATA_BITS_7);
|
||||
break;
|
||||
case data8:
|
||||
if (device->DataBits() != B_DATA_BITS_8)
|
||||
device->SetDataBits(B_DATA_BITS_8);
|
||||
break;
|
||||
default:
|
||||
release_sem(device_sem);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set baud rate
|
||||
data_rate baud_rate;
|
||||
switch (config & 0x03ff) {
|
||||
case baud150: baud_rate = B_150_BPS; break;
|
||||
case baud300: baud_rate = B_300_BPS; break;
|
||||
case baud600: baud_rate = B_600_BPS; break;
|
||||
case baud1200: baud_rate = B_1200_BPS; break;
|
||||
case baud1800: baud_rate = B_1800_BPS; break;
|
||||
case baud2400: baud_rate = B_2400_BPS; break;
|
||||
case baud4800: baud_rate = B_4800_BPS; break;
|
||||
case baud9600: baud_rate = B_9600_BPS; break;
|
||||
case baud19200: baud_rate = B_19200_BPS; break;
|
||||
case baud38400: baud_rate = B_38400_BPS; break;
|
||||
case baud57600: baud_rate = B_57600_BPS; break;
|
||||
default:
|
||||
release_sem(device_sem);
|
||||
return false;
|
||||
}
|
||||
|
||||
D(bug(" baud rate %d, %d stop bits, %s parity, %d data bits\n", baud_rates[baud_rate], device->StopBits() == B_STOP_BITS_1 ? 1 : 2, device->ParityMode() == B_NO_PARITY ? "no" : device->ParityMode() == B_ODD_PARITY ? "odd" : "even", device->DataBits() == B_DATA_BITS_7 ? 7 : 8));
|
||||
if (device->DataRate() != baud_rate) {
|
||||
bool res = device->SetDataRate(baud_rate) == B_OK;
|
||||
release_sem(device_sem);
|
||||
return res;
|
||||
} else {
|
||||
release_sem(device_sem);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set serial handshaking
|
||||
*/
|
||||
|
||||
void BeSERDPort::set_handshake(uint32 s, bool with_dtr)
|
||||
{
|
||||
D(bug(" set_handshake %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
ReadMacInt8(s + 0), ReadMacInt8(s + 1), ReadMacInt8(s + 2), ReadMacInt8(s + 3),
|
||||
ReadMacInt8(s + 4), ReadMacInt8(s + 5), ReadMacInt8(s + 6), ReadMacInt8(s + 7)));
|
||||
if (is_parallel)
|
||||
return;
|
||||
|
||||
uint32 flow;
|
||||
if (with_dtr) {
|
||||
if (ReadMacInt8(s + shkFCTS) || ReadMacInt8(s + shkFDTR))
|
||||
flow = B_HARDWARE_CONTROL;
|
||||
else
|
||||
flow = B_SOFTWARE_CONTROL;
|
||||
} else {
|
||||
if (ReadMacInt8(s + shkFCTS))
|
||||
flow = B_HARDWARE_CONTROL;
|
||||
else
|
||||
flow = B_SOFTWARE_CONTROL;
|
||||
}
|
||||
|
||||
D(bug(" %sware flow control\n", flow == B_HARDWARE_CONTROL ? "hard" : "soft"));
|
||||
while (acquire_sem(device_sem) == B_INTERRUPTED) ;
|
||||
if (device->FlowControl() != flow) {
|
||||
device->Close();
|
||||
device->SetFlowControl(flow);
|
||||
device->Open(device_name);
|
||||
}
|
||||
release_sem(device_sem);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Data input thread
|
||||
*/
|
||||
|
||||
status_t BeSERDPort::input_func(void *arg)
|
||||
{
|
||||
BeSERDPort *s = (BeSERDPort *)arg;
|
||||
for (;;) {
|
||||
|
||||
// Wait for commands
|
||||
thread_id sender;
|
||||
ThreadPacket p;
|
||||
uint32 code = receive_data(&sender, &p, sizeof(ThreadPacket));
|
||||
if (code == CMD_QUIT)
|
||||
break;
|
||||
if (code != CMD_READ)
|
||||
continue;
|
||||
|
||||
// Execute command
|
||||
void *buf = Mac2HostAddr(ReadMacInt32(p.pb + ioBuffer));
|
||||
uint32 length = ReadMacInt32(p.pb + ioReqCount);
|
||||
D(bug("input_func waiting for %ld bytes of data...\n", length));
|
||||
int32 actual;
|
||||
|
||||
// Buffer in kernel space?
|
||||
if ((uint32)buf < 0x80000000) {
|
||||
|
||||
// Yes, transfer via buffer
|
||||
actual = 0;
|
||||
while (length) {
|
||||
uint32 transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
|
||||
int32 transferred;
|
||||
acquire_sem(s->device_sem);
|
||||
if (s->is_parallel) {
|
||||
if ((transferred = read(s->fd, s->tmp_in_buf, transfer_size)) < 0 || s->io_killed) {
|
||||
// Error
|
||||
actual = transferred;
|
||||
release_sem(s->device_sem);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((transferred = s->device->Read(s->tmp_in_buf, transfer_size)) < 0 || s->io_killed) {
|
||||
// Error
|
||||
actual = transferred;
|
||||
release_sem(s->device_sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
release_sem(s->device_sem);
|
||||
memcpy(buf, s->tmp_in_buf, transferred);
|
||||
buf = (void *)((uint8 *)buf + transferred);
|
||||
length -= transferred;
|
||||
actual += transferred;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// No, transfer directly
|
||||
acquire_sem(s->device_sem);
|
||||
if (s->is_parallel)
|
||||
actual = read(s->fd, buf, length);
|
||||
else
|
||||
actual = s->device->Read(buf, length);
|
||||
release_sem(s->device_sem);
|
||||
}
|
||||
|
||||
D(bug(" %ld bytes received\n", actual));
|
||||
|
||||
#if MONITOR
|
||||
bug("Receiving serial data:\n");
|
||||
uint8 *adr = Mac2HostAddr(ReadMacInt32(p.pb + ioBuffer));
|
||||
for (int i=0; i<actual; i++) {
|
||||
bug("%02x ", adr[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
|
||||
// KillIO called? Then simply return
|
||||
if (s->io_killed) {
|
||||
|
||||
WriteMacInt16(p.pb + ioResult, abortErr);
|
||||
WriteMacInt32(p.pb + ioActCount, 0);
|
||||
s->read_pending = s->read_done = false;
|
||||
|
||||
} else {
|
||||
|
||||
// Set error code
|
||||
if (actual >= 0) {
|
||||
WriteMacInt32(p.pb + ioActCount, actual);
|
||||
WriteMacInt32(s->input_dt + serdtResult, noErr);
|
||||
} else {
|
||||
WriteMacInt32(p.pb + ioActCount, 0);
|
||||
WriteMacInt32(s->input_dt + serdtResult, readErr);
|
||||
}
|
||||
|
||||
// Trigger serial interrupt
|
||||
D(bug(" triggering serial interrupt\n"));
|
||||
s->read_done = true;
|
||||
SetInterruptFlag(INTFLAG_SERIAL);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Data output thread
|
||||
*/
|
||||
|
||||
status_t BeSERDPort::output_func(void *arg)
|
||||
{
|
||||
BeSERDPort *s = (BeSERDPort *)arg;
|
||||
for (;;) {
|
||||
|
||||
// Wait for commands
|
||||
thread_id sender;
|
||||
ThreadPacket p;
|
||||
uint32 code = receive_data(&sender, &p, sizeof(ThreadPacket));
|
||||
if (code == CMD_QUIT)
|
||||
break;
|
||||
if (code != CMD_WRITE)
|
||||
continue;
|
||||
|
||||
// Execute command
|
||||
void *buf = Mac2HostAddr(ReadMacInt32(p.pb + ioBuffer));
|
||||
uint32 length = ReadMacInt32(p.pb + ioReqCount);
|
||||
D(bug("output_func transmitting %ld bytes of data...\n", length));
|
||||
int32 actual;
|
||||
|
||||
#if MONITOR
|
||||
bug("Sending serial data:\n");
|
||||
uint8 *adr = (uint8 *)buf;
|
||||
for (int i=0; i<length; i++) {
|
||||
bug("%02x ", adr[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
|
||||
// Buffer in kernel space?
|
||||
if ((uint32)buf < 0x80000000) {
|
||||
|
||||
// Yes, transfer via buffer
|
||||
actual = 0;
|
||||
while (length) {
|
||||
uint32 transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
|
||||
memcpy(s->tmp_out_buf, buf, transfer_size);
|
||||
int32 transferred;
|
||||
acquire_sem(s->device_sem);
|
||||
if (s->is_parallel) {
|
||||
if ((transferred = write(s->fd, s->tmp_out_buf, transfer_size)) < transfer_size || s->io_killed) {
|
||||
if (transferred < 0) // Error
|
||||
actual = transferred;
|
||||
else
|
||||
actual += transferred;
|
||||
release_sem(s->device_sem);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((transferred = s->device->Write(s->tmp_out_buf, transfer_size)) < transfer_size || s->io_killed) {
|
||||
if (transferred < 0) // Error
|
||||
actual = transferred;
|
||||
else
|
||||
actual += transferred;
|
||||
release_sem(s->device_sem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
release_sem(s->device_sem);
|
||||
if (transferred > transfer_size) // R3 parallel port driver bug
|
||||
transferred = transfer_size;
|
||||
buf = (void *)((uint8 *)buf + transferred);
|
||||
length -= transferred;
|
||||
actual += transferred;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// No, transfer directly
|
||||
acquire_sem(s->device_sem);
|
||||
if (s->is_parallel)
|
||||
actual = write(s->fd, buf, length);
|
||||
else
|
||||
actual = s->device->Write(buf, length);
|
||||
release_sem(s->device_sem);
|
||||
if (actual > length) // R3 parallel port driver bug
|
||||
actual = length;
|
||||
}
|
||||
|
||||
D(bug(" %ld bytes transmitted\n", actual));
|
||||
|
||||
// KillIO called? Then simply return
|
||||
if (s->io_killed) {
|
||||
|
||||
WriteMacInt16(p.pb + ioResult, abortErr);
|
||||
WriteMacInt32(p.pb + ioActCount, 0);
|
||||
s->write_pending = s->write_done = false;
|
||||
|
||||
} else {
|
||||
|
||||
// Set error code
|
||||
if (actual >= 0) {
|
||||
WriteMacInt32(p.pb + ioActCount, actual);
|
||||
WriteMacInt32(s->output_dt + serdtResult, noErr);
|
||||
} else {
|
||||
WriteMacInt32(p.pb + ioActCount, 0);
|
||||
WriteMacInt32(s->output_dt + serdtResult, writErr);
|
||||
}
|
||||
|
||||
// Trigger serial interrupt
|
||||
D(bug(" triggering serial interrupt\n"));
|
||||
s->write_done = true;
|
||||
SetInterruptFlag(INTFLAG_SERIAL);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,841 +0,0 @@
|
|||
/*
|
||||
* sys_beos.cpp - System dependent routines, BeOS implementation
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <StorageKit.h>
|
||||
#include <InterfaceKit.h>
|
||||
#include <kernel/fs_info.h>
|
||||
#include <drivers/Drivers.h>
|
||||
#include <device/scsi.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "main.h"
|
||||
#include "macos_util.h"
|
||||
#include "prefs.h"
|
||||
#include "user_strings.h"
|
||||
#include "sys.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <fs_volume.h>
|
||||
#define unmount(x) fs_unmount_volume(x, 0)
|
||||
#endif
|
||||
|
||||
|
||||
// File handles are pointers to these structures
|
||||
struct file_handle {
|
||||
file_handle *next; // Pointer to next file handle (must be first in struct!)
|
||||
const char *name; // File/device name (copied, for mount menu)
|
||||
int fd; // fd of file/device
|
||||
bool is_file; // Flag: plain file or /dev/something?
|
||||
bool read_only; // Copy of Sys_open() flag
|
||||
loff_t start_byte; // Size of file header (if any)
|
||||
loff_t file_size; // Size of file data (only valid if is_file is true)
|
||||
};
|
||||
|
||||
// Linked list of file handles
|
||||
static file_handle *first_file_handle;
|
||||
|
||||
// Temporary buffer for transfers from/to kernel space
|
||||
const int TMP_BUF_SIZE = 0x10000;
|
||||
static uint8 *tmp_buf;
|
||||
|
||||
// For B_SCSI_PREVENT_ALLOW
|
||||
static const int32 PREVENT = 1;
|
||||
static const int32 ALLOW = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Check if device is a mounted HFS volume, get mount name
|
||||
*/
|
||||
|
||||
static bool is_drive_mounted(const char *dev_name, char *mount_name)
|
||||
{
|
||||
int32 i = 0;
|
||||
dev_t d;
|
||||
fs_info info;
|
||||
while ((d = next_dev(&i)) >= 0) {
|
||||
fs_stat_dev(d, &info);
|
||||
if (strcmp(dev_name, info.device_name) == 0) {
|
||||
status_t err = -1;
|
||||
BPath mount;
|
||||
BDirectory dir;
|
||||
BEntry entry;
|
||||
node_ref node;
|
||||
node.device = info.dev;
|
||||
node.node = info.root;
|
||||
err = dir.SetTo(&node);
|
||||
if (!err)
|
||||
err = dir.GetEntry(&entry);
|
||||
if (!err)
|
||||
err = entry.GetPath(&mount);
|
||||
if (!err) {
|
||||
strcpy(mount_name, mount.Path());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void SysInit(void)
|
||||
{
|
||||
first_file_handle = NULL;
|
||||
|
||||
// Allocate temporary buffer
|
||||
tmp_buf = new uint8[TMP_BUF_SIZE];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialization
|
||||
*/
|
||||
|
||||
void SysExit(void)
|
||||
{
|
||||
delete[] tmp_buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create menu of used volumes (for "mount" menu)
|
||||
*/
|
||||
|
||||
void SysCreateVolumeMenu(BMenu *menu, uint32 msg)
|
||||
{
|
||||
for (file_handle *fh=first_file_handle; fh; fh=fh->next)
|
||||
if (!SysIsFixedDisk(fh))
|
||||
menu->AddItem(new BMenuItem(fh->name, new BMessage(msg)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mount volume given name from mount menu
|
||||
*/
|
||||
|
||||
void SysMountVolume(const char *name)
|
||||
{
|
||||
file_handle *fh;
|
||||
for (fh=first_file_handle; fh && strcmp(fh->name, name); fh=fh->next) ;
|
||||
if (fh)
|
||||
MountVolume(fh);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This gets called when no "floppy" prefs items are found
|
||||
* It scans for available floppy drives and adds appropriate prefs items
|
||||
*/
|
||||
|
||||
void SysAddFloppyPrefs(void)
|
||||
{
|
||||
// Only one floppy drive under BeOS
|
||||
PrefsAddString("floppy", "/dev/disk/floppy/raw");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This gets called when no "disk" prefs items are found
|
||||
* It scans for available HFS volumes and adds appropriate prefs items
|
||||
*/
|
||||
|
||||
void SysAddDiskPrefs(void)
|
||||
{
|
||||
// Let BeOS scan for HFS drives
|
||||
D(bug("Looking for Mac volumes...\n"));
|
||||
system("mountvolume -allhfs");
|
||||
|
||||
// Add all HFS volumes
|
||||
int32 i = 0;
|
||||
dev_t d;
|
||||
fs_info info;
|
||||
while ((d = next_dev(&i)) >= 0) {
|
||||
fs_stat_dev(d, &info);
|
||||
status_t err = -1;
|
||||
BPath mount;
|
||||
if (!strcmp(info.fsh_name, "hfs")) {
|
||||
BDirectory dir;
|
||||
BEntry entry;
|
||||
node_ref node;
|
||||
node.device = info.dev;
|
||||
node.node = info.root;
|
||||
err = dir.SetTo(&node);
|
||||
if (!err)
|
||||
err = dir.GetEntry(&entry);
|
||||
if (!err)
|
||||
err = entry.GetPath(&mount);
|
||||
}
|
||||
if (!err)
|
||||
err = unmount(mount.Path());
|
||||
if (!err) {
|
||||
char dev_name[B_FILE_NAME_LENGTH];
|
||||
if (info.flags & B_FS_IS_READONLY) {
|
||||
dev_name[0] = '*';
|
||||
dev_name[1] = 0;
|
||||
} else
|
||||
dev_name[0] = 0;
|
||||
strcat(dev_name, info.device_name);
|
||||
PrefsAddString("disk", dev_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This gets called when no "cdrom" prefs items are found
|
||||
* It scans for available CD-ROM drives and adds appropriate prefs items
|
||||
*/
|
||||
|
||||
// Scan directory for CD-ROM drives, add them to prefs
|
||||
static void scan_for_cdrom_drives(const char *directory)
|
||||
{
|
||||
// Set directory
|
||||
BDirectory dir;
|
||||
dir.SetTo(directory);
|
||||
if (dir.InitCheck() != B_NO_ERROR)
|
||||
return;
|
||||
dir.Rewind();
|
||||
|
||||
// Scan each entry
|
||||
BEntry entry;
|
||||
while (dir.GetNextEntry(&entry) >= 0) {
|
||||
|
||||
// Get path and ref for entry
|
||||
BPath path;
|
||||
if (entry.GetPath(&path) != B_NO_ERROR)
|
||||
continue;
|
||||
const char *name = path.Path();
|
||||
entry_ref e;
|
||||
if (entry.GetRef(&e) != B_NO_ERROR)
|
||||
continue;
|
||||
|
||||
// Recursively enter subdirectories (except for floppy)
|
||||
if (entry.IsDirectory()) {
|
||||
if (!strcmp(e.name, "floppy"))
|
||||
continue;
|
||||
scan_for_cdrom_drives(name);
|
||||
} else {
|
||||
|
||||
D(bug(" checking '%s'\n", name));
|
||||
|
||||
// Ignore partitions
|
||||
if (strcmp(e.name, "raw"))
|
||||
continue;
|
||||
|
||||
// Open device
|
||||
int fd = open(name, O_RDONLY);
|
||||
if (fd < 0)
|
||||
continue;
|
||||
|
||||
// Get geometry and device type
|
||||
device_geometry g;
|
||||
if (ioctl(fd, B_GET_GEOMETRY, &g, sizeof(g)) < 0) {
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Insert to list if it is a CD drive
|
||||
if (g.device_type == B_CD)
|
||||
PrefsAddString("cdrom", name);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SysAddCDROMPrefs(void)
|
||||
{
|
||||
// Don't scan for drives if nocdrom option given
|
||||
if (PrefsFindBool("nocdrom"))
|
||||
return;
|
||||
|
||||
// Look for CD-ROM drives and add prefs items
|
||||
D(bug("Looking for CD-ROM drives...\n"));
|
||||
scan_for_cdrom_drives("/dev/disk");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add default serial prefs (must be added, even if no ports present)
|
||||
*/
|
||||
|
||||
void SysAddSerialPrefs(void)
|
||||
{
|
||||
#ifdef __HAIKU__
|
||||
PrefsAddString("seriala", "serial1");
|
||||
PrefsAddString("serialb", "serial2");
|
||||
#else
|
||||
system_info info;
|
||||
get_system_info(&info);
|
||||
switch (info.platform_type) {
|
||||
case B_BEBOX_PLATFORM:
|
||||
case B_AT_CLONE_PLATFORM:
|
||||
PrefsAddString("seriala", "serial1");
|
||||
PrefsAddString("serialb", "serial2");
|
||||
break;
|
||||
case B_MAC_PLATFORM:
|
||||
PrefsAddString("seriala", "modem");
|
||||
PrefsAddString("serialb", "printer");
|
||||
break;
|
||||
default:
|
||||
PrefsAddString("seriala", "none");
|
||||
PrefsAddString("serialb", "none");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Open file/device, create new file handle (returns NULL on error)
|
||||
*/
|
||||
|
||||
void *Sys_open(const char *name, bool read_only)
|
||||
{
|
||||
static bool published_all = false;
|
||||
bool is_file = (strstr(name, "/dev/") != name);
|
||||
|
||||
D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write"));
|
||||
|
||||
// Print warning message and eventually unmount drive when this is an HFS volume mounted under BeOS (double mounting will corrupt the volume)
|
||||
char mount_name[B_FILE_NAME_LENGTH];
|
||||
if (!is_file && !read_only && is_drive_mounted(name, mount_name)) {
|
||||
char str[256 + B_FILE_NAME_LENGTH];
|
||||
sprintf(str, GetString(STR_VOLUME_IS_MOUNTED_WARN), mount_name);
|
||||
WarningAlert(str);
|
||||
if (unmount(mount_name) != 0) {
|
||||
sprintf(str, GetString(STR_CANNOT_UNMOUNT_WARN), mount_name);
|
||||
WarningAlert(str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int fd = open(name, read_only ? O_RDONLY : O_RDWR);
|
||||
if (fd < 0 && !published_all) {
|
||||
// Open failed, create all device nodes and try again, but only the first time
|
||||
system("mountvolume -publishall");
|
||||
published_all = true;
|
||||
fd = open(name, read_only ? O_RDONLY : O_RDWR);
|
||||
}
|
||||
if (fd >= 0) {
|
||||
file_handle *fh = new file_handle;
|
||||
fh->name = strdup(name);
|
||||
fh->fd = fd;
|
||||
fh->is_file = is_file;
|
||||
fh->read_only = read_only;
|
||||
fh->start_byte = 0;
|
||||
if (fh->is_file) {
|
||||
// Detect disk image file layout
|
||||
loff_t size = lseek(fd, 0, SEEK_END);
|
||||
uint8 data[256];
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
read(fd, data, 256);
|
||||
FileDiskLayout(size, data, fh->start_byte, fh->file_size);
|
||||
}
|
||||
|
||||
// Enqueue file handle
|
||||
fh->next = NULL;
|
||||
file_handle *q = first_file_handle;
|
||||
if (q) {
|
||||
while (q->next)
|
||||
q = q->next;
|
||||
q->next = fh;
|
||||
} else
|
||||
first_file_handle = fh;
|
||||
return fh;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close file/device, delete file handle
|
||||
*/
|
||||
|
||||
void Sys_close(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
// Free device name and close file/device
|
||||
free((void *)fh->name);
|
||||
close(fh->fd);
|
||||
|
||||
// Dequeue file handle
|
||||
file_handle *q = first_file_handle;
|
||||
if (q == fh) {
|
||||
first_file_handle = NULL;
|
||||
delete fh;
|
||||
return;
|
||||
}
|
||||
while (q) {
|
||||
if (q->next == fh) {
|
||||
q->next = fh->next;
|
||||
delete fh;
|
||||
return;
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read "length" bytes from file/device, starting at "offset", to "buffer",
|
||||
* returns number of bytes read (or 0)
|
||||
*/
|
||||
|
||||
static inline ssize_t sread(int fd, void *buf, size_t count)
|
||||
{
|
||||
ssize_t res;
|
||||
while ((res = read(fd, buf, count)) == B_INTERRUPTED) ;
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t Sys_read(void *arg, void *buffer, loff_t offset, size_t length)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return 0;
|
||||
|
||||
// D(bug("Sys_read(%08lx, %08lx, %Ld, %d)\n", fh, buffer, offset, length));
|
||||
|
||||
// Seek to position
|
||||
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
|
||||
return 0;
|
||||
|
||||
// Buffer in kernel space?
|
||||
size_t actual = 0;
|
||||
if ((uint32)buffer < 0x80000000) {
|
||||
|
||||
// Yes, transfer via buffer
|
||||
while (length) {
|
||||
size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
|
||||
if (sread(fh->fd, tmp_buf, transfer_size) != transfer_size)
|
||||
return actual;
|
||||
memcpy(buffer, tmp_buf, transfer_size);
|
||||
buffer = (void *)((uint8 *)buffer + transfer_size);
|
||||
length -= transfer_size;
|
||||
actual += transfer_size;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// No, transfer directly
|
||||
actual = sread(fh->fd, buffer, length);
|
||||
if (actual < 0)
|
||||
actual = 0;
|
||||
}
|
||||
return actual;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write "length" bytes from "buffer" to file/device, starting at "offset",
|
||||
* returns number of bytes written (or 0)
|
||||
*/
|
||||
|
||||
static inline ssize_t swrite(int fd, void *buf, size_t count)
|
||||
{
|
||||
ssize_t res;
|
||||
while ((res = write(fd, buf, count)) == B_INTERRUPTED) ;
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t Sys_write(void *arg, void *buffer, loff_t offset, size_t length)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return 0;
|
||||
|
||||
// D(bug("Sys_write(%08lx, %08lx, %Ld, %d)\n", fh, buffer, offset, length));
|
||||
|
||||
// Seek to position
|
||||
if (lseek(fh->fd, offset + fh->start_byte, SEEK_SET) < 0)
|
||||
return 0;
|
||||
|
||||
// Buffer in kernel space?
|
||||
size_t actual = 0;
|
||||
if ((uint32)buffer < 0x80000000) {
|
||||
|
||||
// Yes, transfer via buffer
|
||||
while (length) {
|
||||
size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
|
||||
memcpy(tmp_buf, buffer, transfer_size);
|
||||
if (swrite(fh->fd, tmp_buf, transfer_size) != transfer_size)
|
||||
return actual;
|
||||
buffer = (void *)((uint8 *)buffer + transfer_size);
|
||||
length -= transfer_size;
|
||||
actual += transfer_size;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// No, transfer directly
|
||||
actual = swrite(fh->fd, buffer, length);
|
||||
if (actual < 0)
|
||||
actual = 0;
|
||||
}
|
||||
return actual;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return size of file/device (minus header)
|
||||
*/
|
||||
|
||||
loff_t SysGetFileSize(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return true;
|
||||
|
||||
if (fh->is_file)
|
||||
return fh->file_size;
|
||||
else {
|
||||
device_geometry g;
|
||||
if (ioctl(fh->fd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0)
|
||||
return (loff_t)g.bytes_per_sector * g.sectors_per_track * g.cylinder_count * g.head_count;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Eject volume (if applicable)
|
||||
*/
|
||||
|
||||
void SysEject(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
if (!fh->is_file)
|
||||
ioctl(fh->fd, B_EJECT_DEVICE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Format volume (if applicable)
|
||||
*/
|
||||
|
||||
bool SysFormat(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (!fh->is_file)
|
||||
return ioctl(fh->fd, B_FORMAT_DEVICE) >= 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if file/device is read-only (this includes the read-only flag on Sys_open())
|
||||
*/
|
||||
|
||||
bool SysIsReadOnly(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return true;
|
||||
|
||||
if (fh->is_file) {
|
||||
|
||||
// File, return flag given to Sys_open
|
||||
return fh->read_only;
|
||||
|
||||
} else {
|
||||
|
||||
// Device, check write protection
|
||||
device_geometry g;
|
||||
if (ioctl(fh->fd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0)
|
||||
return g.read_only | fh->read_only;
|
||||
else
|
||||
return fh->read_only; // Removable but not inserted
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if the given file handle refers to a fixed or a removable disk
|
||||
*/
|
||||
|
||||
bool SysIsFixedDisk(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return true;
|
||||
|
||||
if (fh->is_file)
|
||||
return true;
|
||||
else {
|
||||
device_geometry g;
|
||||
if (ioctl(fh->fd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0)
|
||||
return !g.removable;
|
||||
else
|
||||
return false; // Removable but not inserted
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if a disk is inserted in the drive (always true for files)
|
||||
*/
|
||||
|
||||
bool SysIsDiskInserted(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (fh->is_file)
|
||||
return true;
|
||||
else {
|
||||
status_t l;
|
||||
if (ioctl(fh->fd, B_GET_MEDIA_STATUS, &l, sizeof(l)) >= 0 && l == B_NO_ERROR)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prevent medium removal (if applicable)
|
||||
*/
|
||||
|
||||
void SysPreventRemoval(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
if (!fh->is_file)
|
||||
ioctl(fh->fd, B_SCSI_PREVENT_ALLOW, &PREVENT, sizeof(PREVENT));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allow medium removal (if applicable)
|
||||
*/
|
||||
|
||||
void SysAllowRemoval(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
if (!fh->is_file)
|
||||
ioctl(fh->fd, B_SCSI_PREVENT_ALLOW, &ALLOW, sizeof(ALLOW));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read CD-ROM TOC (binary MSF format, 804 bytes max.)
|
||||
*/
|
||||
|
||||
bool SysCDReadTOC(void *arg, uint8 *toc)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (!fh->is_file) {
|
||||
memset(tmp_buf, 0, 804);
|
||||
if (ioctl(fh->fd, B_SCSI_GET_TOC, tmp_buf, 804) < 0)
|
||||
return false;
|
||||
memcpy(toc, tmp_buf, 804);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read CD-ROM position data (Sub-Q Channel, 16 bytes, see SCSI standard)
|
||||
*/
|
||||
|
||||
bool SysCDGetPosition(void *arg, uint8 *pos)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (!fh->is_file) {
|
||||
if (ioctl(fh->fd, B_SCSI_GET_POSITION, tmp_buf, 16) < 0)
|
||||
return false;
|
||||
memcpy(pos, tmp_buf, 16);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Play CD audio
|
||||
*/
|
||||
|
||||
bool SysCDPlay(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, uint8 end_m, uint8 end_s, uint8 end_f)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (!fh->is_file) {
|
||||
scsi_play_position *p = (scsi_play_position *)tmp_buf;
|
||||
p->start_m = start_m;
|
||||
p->start_s = start_s;
|
||||
p->start_f = start_f;
|
||||
p->end_m = end_m;
|
||||
p->end_s = end_s;
|
||||
p->end_f = end_f;
|
||||
return ioctl(fh->fd, B_SCSI_PLAY_POSITION, p, sizeof(scsi_play_position)) == 0;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pause CD audio
|
||||
*/
|
||||
|
||||
bool SysCDPause(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return true;
|
||||
|
||||
if (!fh->is_file)
|
||||
return ioctl(fh->fd, B_SCSI_PAUSE_AUDIO) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resume paused CD audio
|
||||
*/
|
||||
|
||||
bool SysCDResume(void *arg)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (!fh->is_file)
|
||||
return ioctl(fh->fd, B_SCSI_RESUME_AUDIO) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stop CD audio
|
||||
*/
|
||||
|
||||
bool SysCDStop(void *arg, uint8 lead_out_m, uint8 lead_out_s, uint8 lead_out_f)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (!fh->is_file)
|
||||
return ioctl(fh->fd, B_SCSI_STOP_AUDIO) == 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform CD audio fast-forward/fast-reverse operation starting from specified address
|
||||
*/
|
||||
|
||||
bool SysCDScan(void *arg, uint8 start_m, uint8 start_s, uint8 start_f, bool reverse)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return false;
|
||||
|
||||
if (!fh->is_file) {
|
||||
scsi_scan *p = (scsi_scan *)tmp_buf;
|
||||
p->speed = 0;
|
||||
p->direction = reverse ? -1 : 1;
|
||||
return ioctl(fh->fd, B_SCSI_SCAN, p, sizeof(scsi_scan)) == 0;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set CD audio volume (0..255 each channel)
|
||||
*/
|
||||
|
||||
void SysCDSetVolume(void *arg, uint8 left, uint8 right)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
if (!fh->is_file) {
|
||||
scsi_volume *p = (scsi_volume *)tmp_buf;
|
||||
p->flags = B_SCSI_PORT0_VOLUME | B_SCSI_PORT1_VOLUME;
|
||||
p->port0_volume = left;
|
||||
p->port1_volume = right;
|
||||
ioctl(fh->fd, B_SCSI_SET_VOLUME, p, sizeof(scsi_volume));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get CD audio volume (0..255 each channel)
|
||||
*/
|
||||
|
||||
void SysCDGetVolume(void *arg, uint8 &left, uint8 &right)
|
||||
{
|
||||
file_handle *fh = (file_handle *)arg;
|
||||
if (!fh)
|
||||
return;
|
||||
|
||||
left = right = 0;
|
||||
if (!fh->is_file) {
|
||||
scsi_volume *p = (scsi_volume *)tmp_buf;
|
||||
p->flags = B_SCSI_PORT0_VOLUME | B_SCSI_PORT1_VOLUME;
|
||||
if (ioctl(fh->fd, B_SCSI_GET_VOLUME, p, sizeof(scsi_volume)) == 0) {
|
||||
left = p->port0_volume;
|
||||
right = p->port1_volume;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
* sysdeps.h - System dependent definitions for BeOS
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SYSDEPS_H
|
||||
#define SYSDEPS_H
|
||||
|
||||
#ifdef __POWERPC__
|
||||
#define NO_STD_NAMESPACE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <support/SupportDefs.h>
|
||||
#include <support/ByteOrder.h>
|
||||
|
||||
#include "user_strings_beos.h"
|
||||
|
||||
// Are the Mac and the host address space the same?
|
||||
#ifdef __i386__
|
||||
#define REAL_ADDRESSING 0
|
||||
#undef WORDS_BIGENDIAN
|
||||
#else
|
||||
#define REAL_ADDRESSING 1
|
||||
#define WORDS_BIGENDIAN 1
|
||||
#endif
|
||||
|
||||
// Using 68k emulator
|
||||
#define EMULATED_68K 1
|
||||
|
||||
// Mac ROM is write protected
|
||||
#define ROM_IS_WRITE_PROTECTED 1
|
||||
|
||||
// ExtFS is supported
|
||||
#define SUPPORTS_EXTFS 1
|
||||
|
||||
// BSD socket API is supported
|
||||
#define SUPPORTS_UDP_TUNNEL 1
|
||||
|
||||
// mon is not supported
|
||||
#undef ENABLE_MON
|
||||
|
||||
// Time data type for Time Manager emulation
|
||||
typedef bigtime_t tm_time_t;
|
||||
|
||||
// 64 bit file offsets
|
||||
typedef off_t loff_t;
|
||||
|
||||
// Networking types
|
||||
#define PF_INET AF_INET
|
||||
#ifndef __HAIKU__
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
// UAE CPU data types
|
||||
#define uae_s8 int8
|
||||
#define uae_u8 uint8
|
||||
#define uae_s16 int16
|
||||
#define uae_u16 uint16
|
||||
#define uae_s32 int32
|
||||
#define uae_u32 uint32
|
||||
#define uae_s64 int64
|
||||
#define uae_u64 uint64
|
||||
typedef uae_u32 uaecptr;
|
||||
#define VAL64(a) (a ## LL)
|
||||
#define UVAL64(a) (a ## uLL)
|
||||
typedef uint32 uintptr;
|
||||
typedef int32 intptr;
|
||||
|
||||
/* Timing functions */
|
||||
extern void Delay_usec(uint32 usec);
|
||||
|
||||
// UAE CPU defines
|
||||
#ifdef __i386__
|
||||
|
||||
// Intel x86 assembler optimizations
|
||||
#define X86_PPRO_OPT
|
||||
static inline uae_u32 do_get_mem_long(uae_u32 *a) {uint32 retval; __asm__ ("bswap %0" : "=r" (retval) : "0" (*a) : "cc"); return retval;}
|
||||
#ifdef X86_PPRO_OPT
|
||||
static inline uae_u32 do_get_mem_word(uae_u16 *a) {uint32 retval; __asm__ ("movzwl %w1,%k0\n\tshll $16,%k0\n\tbswap %k0\n" : "=&r" (retval) : "m" (*a) : "cc"); return retval;}
|
||||
#else
|
||||
static inline uae_u32 do_get_mem_word(uae_u16 *a) {uint32 retval; __asm__ ("xorl %k0,%k0\n\tmovw %w1,%w0\n\trolw $8,%w0" : "=&r" (retval) : "m" (*a) : "cc"); return retval;}
|
||||
#endif
|
||||
#define HAVE_GET_WORD_UNSWAPPED
|
||||
#define do_get_mem_word_unswapped(a) ((uae_u32)*((uae_u16 *)(a)))
|
||||
static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {__asm__ ("bswap %0" : "=r" (v) : "0" (v) : "cc"); *a = v;}
|
||||
#ifdef X86_PPRO_OPT
|
||||
static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {__asm__ ("bswap %0" : "=&r" (v) : "0" (v << 16) : "cc"); *a = v;}
|
||||
#else
|
||||
static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {__asm__ ("rolw $8,%0" : "=r" (v) : "0" (v) : "cc"); *a = v;}
|
||||
#endif
|
||||
|
||||
#define X86_ASSEMBLY
|
||||
#define UNALIGNED_PROFITABLE
|
||||
#define OPTIMIZED_FLAGS
|
||||
#define ASM_SYM(a) __asm__(a)
|
||||
#define REGPARAM __attribute__((regparm(3)))
|
||||
|
||||
#else
|
||||
|
||||
// PowerPC (memory.cpp not used, so no optimization neccessary)
|
||||
static inline uae_u32 do_get_mem_long(uae_u32 *a) {return *a;}
|
||||
static inline uae_u32 do_get_mem_word(uae_u16 *a) {return *a;}
|
||||
static inline void do_put_mem_long(uae_u32 *a, uae_u32 v) {*a = v;}
|
||||
static inline void do_put_mem_word(uae_u16 *a, uae_u32 v) {*a = v;}
|
||||
|
||||
#undef X86_ASSEMBLY
|
||||
#define UNALIGNED_PROFITABLE
|
||||
#undef OPTIMIZED_FLAGS
|
||||
#define ASM_SYM(a)
|
||||
#define REGPARAM
|
||||
#endif
|
||||
|
||||
#define do_get_mem_byte(a) ((uae_u32)*((uae_u8 *)(a)))
|
||||
#define do_put_mem_byte(a, v) (*(uae_u8 *)(a) = (v))
|
||||
|
||||
#define call_mem_get_func(func, addr) ((*func)(addr))
|
||||
#define call_mem_put_func(func, addr, v) ((*func)(addr, v))
|
||||
#define __inline__ inline
|
||||
#define CPU_EMU_SIZE 0
|
||||
#undef NO_INLINE_MEMORY_ACCESS
|
||||
#undef MD_HAVE_MEM_1_FUNCS
|
||||
#undef USE_COMPILER
|
||||
#define REGPARAM2
|
||||
#define ENUMDECL typedef enum
|
||||
#define ENUMNAME(name) name
|
||||
#define write_log printf
|
||||
|
||||
#endif
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* timer_beos.cpp - Time Manager emulation, BeOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <KernelKit.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "macos_util.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// From main_beos.cpp
|
||||
extern thread_id emul_thread;
|
||||
|
||||
|
||||
/*
|
||||
* Return microseconds since boot (64 bit)
|
||||
*/
|
||||
|
||||
void Microseconds(uint32 &hi, uint32 &lo)
|
||||
{
|
||||
D(bug("Microseconds\n"));
|
||||
bigtime_t time = system_time();
|
||||
hi = time >> 32;
|
||||
lo = time;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return local date/time in Mac format (seconds since 1.1.1904)
|
||||
*/
|
||||
|
||||
uint32 TimerDateTime(void)
|
||||
{
|
||||
return TimeToMacTime(time(NULL));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get current time
|
||||
*/
|
||||
|
||||
void timer_current_time(tm_time_t &t)
|
||||
{
|
||||
t = system_time();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add times
|
||||
*/
|
||||
|
||||
void timer_add_time(tm_time_t &res, tm_time_t a, tm_time_t b)
|
||||
{
|
||||
res = a + b;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Subtract times
|
||||
*/
|
||||
|
||||
void timer_sub_time(tm_time_t &res, tm_time_t a, tm_time_t b)
|
||||
{
|
||||
res = a - b;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compare times (<0: a < b, =0: a = b, >0: a > b)
|
||||
*/
|
||||
|
||||
int timer_cmp_time(tm_time_t a, tm_time_t b)
|
||||
{
|
||||
tm_time_t r = a - b;
|
||||
return r < 0 ? -1 : (r > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert Mac time value (>0: microseconds, <0: microseconds) to tm_time_t
|
||||
*/
|
||||
|
||||
void timer_mac2host_time(tm_time_t &res, int32 mactime)
|
||||
{
|
||||
if (mactime > 0)
|
||||
res = mactime * 1000; // Time in milliseconds
|
||||
else
|
||||
res = -mactime; // Time in negative microseconds
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert positive tm_time_t to Mac time value (>0: microseconds, <0: microseconds)
|
||||
* A negative input value for hosttime results in a zero return value
|
||||
* As long as the microseconds value fits in 32 bit, it must not be converted to milliseconds!
|
||||
*/
|
||||
|
||||
int32 timer_host2mac_time(tm_time_t hosttime)
|
||||
{
|
||||
if (hosttime < 0)
|
||||
return 0;
|
||||
else if (hosttime > 0x7fffffff)
|
||||
return hosttime / 1000; // Time in milliseconds
|
||||
else
|
||||
return -hosttime; // Time in negative microseconds
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delay by specified number of microseconds (<1 second)
|
||||
*/
|
||||
|
||||
void Delay_usec(uint32 usec)
|
||||
{
|
||||
snooze(usec);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Suspend emulator thread, virtual CPU in idle mode
|
||||
*/
|
||||
|
||||
void idle_wait(void)
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
FIXME: add a semaphore (counter) to avoid a B_BAD_THREAD_STATE
|
||||
return if we call idle_resume() when thread is not suspended?
|
||||
|
||||
Sorry, I can't test -- gb.
|
||||
*/
|
||||
suspend_thread(emul_thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resume execution of emulator thread, events just arrived
|
||||
*/
|
||||
|
||||
void idle_resume(void)
|
||||
{
|
||||
#if 0
|
||||
resume_thread(emul_thread);
|
||||
#endif
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* user_strings_beos.cpp - BeOS-specific localizable strings
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "user_strings.h"
|
||||
|
||||
|
||||
// Platform-specific string definitions
|
||||
user_string_def platform_strings[] = {
|
||||
// Common strings that have a platform-specific variant
|
||||
{STR_VOLUME_IS_MOUNTED_WARN, "The volume '%s' is mounted under BeOS. Basilisk II will try to unmount it."},
|
||||
{STR_EXTFS_CTRL, "BeOS Root"},
|
||||
{STR_EXTFS_NAME, "BeOS Directory Tree"},
|
||||
{STR_EXTFS_VOLUME_NAME, "BeOS"},
|
||||
|
||||
// Purely platform-specific strings
|
||||
{STR_NO_SHEEP_DRIVER_ERR, "Cannot open /dev/sheep: %s (%08x). Basilisk II is not properly installed."},
|
||||
{STR_SHEEP_UP_ERR, "Cannot allocate Low Memory Globals: %s (%08x)."},
|
||||
{STR_NO_KERNEL_DATA_ERR, "Cannot create Kernel Data area: %s (%08x)."},
|
||||
{STR_NO_NET_ADDON_WARN, "The SheepShaver net server add-on cannot be found. Ethernet will not be available."},
|
||||
{STR_NET_CONFIG_MODIFY_WARN, "To enable Ethernet networking for Basilisk II, your network configuration has to be modified and the network restarted. Do you want this to be done now (selecting \"Cancel\" will disable Ethernet under Basilisk II)?."},
|
||||
{STR_NET_ADDON_INIT_FAILED, "SheepShaver net server add-on found\nbut there seems to be no network hardware.\nPlease check your network preferences."},
|
||||
{STR_NET_ADDON_CLONE_FAILED, "Cloning of the network transfer area failed."},
|
||||
{STR_VIDEO_FAILED, "Failed to set video mode."},
|
||||
|
||||
{-1, NULL} // End marker
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Fetch pointer to string, given the string number
|
||||
*/
|
||||
|
||||
const char *GetString(int num)
|
||||
{
|
||||
// First search for platform-specific string
|
||||
int i = 0;
|
||||
while (platform_strings[i].num >= 0) {
|
||||
if (platform_strings[i].num == num)
|
||||
return platform_strings[i].str;
|
||||
i++;
|
||||
}
|
||||
|
||||
// Not found, search for common string
|
||||
i = 0;
|
||||
while (common_strings[i].num >= 0) {
|
||||
if (common_strings[i].num == num)
|
||||
return common_strings[i].str;
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* user_strings_beos.h - BeOS-specific localizable strings
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef USER_STRINGS_BEOS_H
|
||||
#define USER_STRINGS_BEOS_H
|
||||
|
||||
enum {
|
||||
STR_NO_SHEEP_DRIVER_ERR = 10000,
|
||||
STR_SHEEP_UP_ERR,
|
||||
STR_NO_KERNEL_DATA_ERR,
|
||||
STR_NO_NET_ADDON_WARN,
|
||||
STR_NET_CONFIG_MODIFY_WARN,
|
||||
STR_NET_ADDON_INIT_FAILED,
|
||||
STR_NET_ADDON_CLONE_FAILED,
|
||||
STR_VIDEO_FAILED
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* xpram_beos.cpp - XPRAM handling, BeOS specific stuff
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <StorageKit.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "xpram.h"
|
||||
|
||||
|
||||
// XPRAM file name and path
|
||||
#if POWERPC_ROM
|
||||
const char XPRAM_FILE_NAME[] = "SheepShaver_NVRAM";
|
||||
#else
|
||||
const char XPRAM_FILE_NAME[] = "BasiliskII_XPRAM";
|
||||
#endif
|
||||
static BPath xpram_path;
|
||||
|
||||
|
||||
/*
|
||||
* Load XPRAM from settings file
|
||||
*/
|
||||
|
||||
void LoadXPRAM(const char *vmdir)
|
||||
{
|
||||
// Construct XPRAM path
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, &xpram_path, true);
|
||||
xpram_path.Append(XPRAM_FILE_NAME);
|
||||
|
||||
// Load XPRAM from settings file
|
||||
int fd;
|
||||
if ((fd = open(xpram_path.Path(), O_RDONLY)) >= 0) {
|
||||
read(fd, XPRAM, XPRAM_SIZE);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save XPRAM to settings file
|
||||
*/
|
||||
|
||||
void SaveXPRAM(void)
|
||||
{
|
||||
if (xpram_path.InitCheck() != B_NO_ERROR)
|
||||
return;
|
||||
int fd;
|
||||
if ((fd = open(xpram_path.Path(), O_WRONLY | O_CREAT, 0666)) >= 0) {
|
||||
write(fd, XPRAM, XPRAM_SIZE);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete PRAM file
|
||||
*/
|
||||
|
||||
void ZapPRAM(void)
|
||||
{
|
||||
// Construct PRAM path
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, &xpram_path, true);
|
||||
xpram_path.Append(XPRAM_FILE_NAME);
|
||||
|
||||
// Delete file
|
||||
unlink(xpram_path.Path());
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
* $Id$
|
||||
*
|
||||
* video_macosx.mm - Interface between Basilisk II and Cocoa windowing.
|
||||
* Based on video_amiga.cpp and video_x.cpp
|
||||
* Based on video_x.cpp
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
|
@ -51,7 +51,7 @@
|
|||
|
||||
// Global variables
|
||||
uint8 display_type = DISPLAY_WINDOW, // These are used by PrefsEditor
|
||||
frame_skip;
|
||||
frame_skip;
|
||||
uint16 init_width = MIN_WIDTH, // as well as this code
|
||||
init_height = MIN_HEIGHT,
|
||||
init_depth = 32;
|
||||
|
@ -919,7 +919,7 @@ OSX_monitor::switch_to_current_mode(void)
|
|||
const char *failure = NULL;
|
||||
|
||||
D(bug("switch_to_current_mode(): width=%d height=%d depth=%d bytes_per_row=%d\n", mode.x, mode.y, bits_from_depth(mode.depth), mode.bytes_per_row));
|
||||
|
||||
|
||||
if ( display_type == DISPLAY_SCREEN && originalMode )
|
||||
{
|
||||
D(NSLog(@"About to call CGDisplayBestModeForParameters()"));
|
||||
|
@ -958,7 +958,7 @@ OSX_monitor::switch_to_current_mode(void)
|
|||
CGColorSpaceRef oldColourSpace = colourSpace;
|
||||
CGDataProviderRef oldProvider = provider;
|
||||
void *oldBuffer = the_buffer;
|
||||
|
||||
|
||||
if ( video_open(mode) )
|
||||
{
|
||||
CGImageRelease(oldImageRef);
|
||||
|
@ -979,7 +979,7 @@ OSX_monitor::switch_to_current_mode(void)
|
|||
// if ( CGDisplayMoveCursorToPoint(theDisplay, CGPointMake(15,15))
|
||||
// == CGDisplayNoErr )
|
||||
// {
|
||||
//
|
||||
//
|
||||
[output fullscreenMouseMove];
|
||||
// }
|
||||
// else
|
||||
|
|
|
@ -41,7 +41,7 @@ and a Macintosh ROM image to use Basilisk II.
|
|||
.TP
|
||||
- Emulates extended ADB keyboard and 3-button mouse
|
||||
.TP
|
||||
- Uses UAE 68k emulation or (under AmigaOS and NetBSD/m68k) real 68k processor
|
||||
- Uses UAE 68k emulation or real 68k processor
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI "\-\-display " display-name
|
||||
|
|
|
@ -139,17 +139,17 @@ bool open_audio(void)
|
|||
}
|
||||
alSetChannels(config, audio_channel_counts[audio_channel_count_index]);
|
||||
alSetDevice(config, AL_DEFAULT_OUTPUT); // Allow selecting via prefs?
|
||||
|
||||
|
||||
// Try to open the audio library
|
||||
|
||||
port = alOpenPort("BasiliskII", "w", config);
|
||||
if (port == NULL) {
|
||||
fprintf(stderr, "ERROR: Cannot open audio port: %s\n",
|
||||
fprintf(stderr, "ERROR: Cannot open audio port: %s\n",
|
||||
alGetErrorString(oserror()));
|
||||
WarningAlert(GetString(STR_NO_AUDIO_WARN));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Set the sample rate
|
||||
|
||||
pv[0].param = AL_RATE;
|
||||
|
@ -180,7 +180,7 @@ bool open_audio(void)
|
|||
|
||||
// Put a limit on the Mac sound buffer size, to decrease delay
|
||||
#define AUDIO_BUFFER_MSEC 50 // milliseconds of sound to buffer
|
||||
int target_frames_per_block =
|
||||
int target_frames_per_block =
|
||||
(audio_sample_rates[audio_sample_rate_index] >> 16) *
|
||||
AUDIO_BUFFER_MSEC / 1000;
|
||||
if (audio_frames_per_block > target_frames_per_block)
|
||||
|
@ -190,14 +190,14 @@ bool open_audio(void)
|
|||
alZeroFrames(port, audio_frames_per_block); // so we don't underflow
|
||||
|
||||
// Try to keep the buffer pretty full
|
||||
sound_buffer_fill_point = alGetQueueSize(config) -
|
||||
sound_buffer_fill_point = alGetQueueSize(config) -
|
||||
2 * audio_frames_per_block;
|
||||
if (sound_buffer_fill_point < 0)
|
||||
sound_buffer_fill_point = alGetQueueSize(config) / 3;
|
||||
D(bug("fill point %d\n", sound_buffer_fill_point));
|
||||
|
||||
sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) *
|
||||
audio_channel_counts[audio_channel_count_index] *
|
||||
audio_channel_counts[audio_channel_count_index] *
|
||||
audio_frames_per_block;
|
||||
set_audio_status_format();
|
||||
|
||||
|
@ -342,7 +342,7 @@ static void *stream_func(void *arg)
|
|||
goto silence;
|
||||
|
||||
// Send data to audio library. Convert 8-bit data
|
||||
// unsigned->signed, using same algorithm as audio_amiga.cpp.
|
||||
// unsigned->signed
|
||||
// It works fine for 8-bit mono, but not stereo.
|
||||
if (AudioStatus.sample_size == 8) {
|
||||
uint32 *p = (uint32 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
|
||||
|
@ -473,7 +473,7 @@ static void set_volume(uint32 vol)
|
|||
|
||||
alGetParamInfo(dev, AL_GAIN, &pi);
|
||||
maxgain = alFixedToDouble(pi.max.ll);
|
||||
mingain = alFixedToDouble(pi.min.ll);
|
||||
mingain = alFixedToDouble(pi.min.ll);
|
||||
|
||||
// Set the new gain values
|
||||
|
||||
|
|
|
@ -56,12 +56,7 @@ using std::map;
|
|||
|
||||
#define MONITOR 0
|
||||
|
||||
|
||||
#ifdef __BEOS__
|
||||
#define CLOSESOCKET closesocket
|
||||
#else
|
||||
#define CLOSESOCKET close
|
||||
#endif
|
||||
|
||||
|
||||
// Global variables
|
||||
|
@ -138,12 +133,8 @@ void EtherInit(void)
|
|||
|
||||
// Set socket options
|
||||
int on = 1;
|
||||
#ifdef __BEOS__
|
||||
setsockopt(udp_socket, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(on));
|
||||
#else
|
||||
setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
|
||||
ioctl(udp_socket, FIONBIO, &on);
|
||||
#endif
|
||||
|
||||
// Start thread for packet reception
|
||||
if (!ether_start_udp_thread(udp_socket)) {
|
||||
|
|
|
@ -1053,7 +1053,7 @@ static int16 fs_volume_mount(uint32 pb)
|
|||
|
||||
// Init VCB
|
||||
WriteMacInt16(vcb + vcbSigWord, 0x4244);
|
||||
#if defined(__BEOS__) || defined(WIN32)
|
||||
#if defined(WIN32)
|
||||
WriteMacInt32(vcb + vcbCrDate, TimeToMacTime(root_stat.st_crtime));
|
||||
#elif defined __APPLE__ && defined __MACH__
|
||||
WriteMacInt32(vcb + vcbCrDate, get_creation_time(RootPath));
|
||||
|
@ -1118,7 +1118,7 @@ static int16 fs_get_vol_info(uint32 pb, bool hfs)
|
|||
// Fill in struct
|
||||
if (ReadMacInt32(pb + ioNamePtr))
|
||||
pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), VOLUME_NAME);
|
||||
#if defined(__BEOS__) || defined(WIN32)
|
||||
#if defined(WIN32)
|
||||
WriteMacInt32(pb + ioVCrDate, TimeToMacTime(root_stat.st_crtime));
|
||||
#elif defined __APPLE__ && defined __MACH__
|
||||
WriteMacInt32(pb + ioVCrDate, get_creation_time(RootPath));
|
||||
|
@ -1312,7 +1312,7 @@ read_next_de:
|
|||
WriteMacInt8(pb + ioFlAttrib, access(full_path, W_OK) == 0 ? 0 : faLocked);
|
||||
WriteMacInt32(pb + ioDirID, fs_item->id);
|
||||
|
||||
#if defined(__BEOS__) || defined(WIN32)
|
||||
#if defined(WIN32)
|
||||
WriteMacInt32(pb + ioFlCrDat, TimeToMacTime(st.st_crtime));
|
||||
#elif defined __APPLE__ && defined __MACH__
|
||||
WriteMacInt32(pb + ioFlCrDat, get_creation_time(full_path));
|
||||
|
@ -1437,7 +1437,7 @@ read_next_de:
|
|||
WriteMacInt8(pb + ioACUser, 0);
|
||||
WriteMacInt32(pb + ioDirID, fs_item->id);
|
||||
WriteMacInt32(pb + ioFlParID, fs_item->parent_id);
|
||||
#if defined(__BEOS__) || defined(WIN32)
|
||||
#if defined(WIN32)
|
||||
WriteMacInt32(pb + ioFlCrDat, TimeToMacTime(st.st_crtime));
|
||||
#elif defined __APPLE__ && defined __MACH__
|
||||
WriteMacInt32(pb + ioFlCrDat, get_creation_time(full_path));
|
||||
|
|
|
@ -89,18 +89,6 @@ static inline void _cdecl winbug(wchar_t *s, ...)
|
|||
#define bug winbug
|
||||
#define wbug wwinbug
|
||||
|
||||
#elif defined(AMIGA)
|
||||
|
||||
// Amiga debugging info goes to serial port (or sushi)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern void kprintf(const char *, ...);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define bug kprintf
|
||||
|
||||
#else
|
||||
|
||||
// Other systems just print it to stdout
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (Apple PowerMac ROM 680x0 emulator version (BeOS/PPC))
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef CPU_EMULATION_H
|
||||
#define CPU_EMULATION_H
|
||||
|
||||
|
||||
/*
|
||||
* Memory system
|
||||
*/
|
||||
|
||||
// RAM and ROM pointers (allocated and set by main_*.cpp)
|
||||
extern uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0
|
||||
extern uint8 *RAMBaseHost; // RAM base (host address space)
|
||||
extern uint32 RAMSize; // Size of RAM
|
||||
|
||||
extern uint32 ROMBaseMac; // ROM base (Mac address space)
|
||||
extern uint8 *ROMBaseHost; // ROM base (host address space)
|
||||
extern uint32 ROMSize; // Size of ROM
|
||||
|
||||
// Mac memory access functions
|
||||
static inline uint32 ReadMacInt32(uint32 addr) {return ntohl(*(uint32 *)addr);}
|
||||
static inline uint32 ReadMacInt16(uint32 addr) {return ntohs(*(uint16 *)addr);}
|
||||
static inline uint32 ReadMacInt8(uint32 addr) {return *(uint8 *)addr;}
|
||||
static inline void WriteMacInt32(uint32 addr, uint32 l) {*(uint32 *)addr = htonl(l);}
|
||||
static inline void WriteMacInt16(uint32 addr, uint32 w) {*(uint16 *)addr = htons(w);}
|
||||
static inline void WriteMacInt8(uint32 addr, uint32 b) {*(uint8 *)addr = b;}
|
||||
static inline uint8 *Mac2HostAddr(uint32 addr) {return (uint8 *)addr;}
|
||||
static inline uint32 Host2MacAddr(uint8 *addr) {return (uint32)addr;}
|
||||
|
||||
|
||||
/*
|
||||
* 680x0 emulation
|
||||
*/
|
||||
|
||||
// Initialization
|
||||
extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation
|
||||
extern void Exit680x0(void);
|
||||
|
||||
// 680x0 emulation functions
|
||||
struct M68kRegisters;
|
||||
extern void Start680x0(void); // Reset and start 680x0
|
||||
extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine
|
||||
extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine
|
||||
|
||||
// Interrupt functions
|
||||
extern void TriggerInterrupt(void); // Trigger interrupt (InterruptFlag must be set first)
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1040,7 +1040,7 @@ static bool patch_rom_32(void)
|
|||
if (PatchHWBases) {
|
||||
extern uint8 *ScratchMem;
|
||||
const uint32 ScratchMemBase = Host2MacAddr(ScratchMem);
|
||||
|
||||
|
||||
D(bug("LMGlob\tOfs/4\tBase\n"));
|
||||
base = ROMBaseMac + UniversalInfo + ReadMacInt32(ROMBaseMac + UniversalInfo); // decoderInfoPtr
|
||||
wp = (uint16 *)(ROMBaseHost + 0x94a);
|
||||
|
@ -1048,7 +1048,7 @@ static bool patch_rom_32(void)
|
|||
int16 ofs = ntohs(*wp++); // offset in decoderInfo (/4)
|
||||
int16 lmg = ntohs(*wp++); // address of LowMem global
|
||||
D(bug("0x%04x\t%d\t0x%08x\n", lmg, ofs, ReadMacInt32(base + ofs*4)));
|
||||
|
||||
|
||||
// Fake address only if this is not the ASC base
|
||||
if (lmg != 0xcc0)
|
||||
WriteMacInt32(base + ofs*4, ScratchMemBase);
|
||||
|
@ -1280,20 +1280,13 @@ static bool patch_rom_32(void)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if REAL_ADDRESSING && defined(AMIGA)
|
||||
// Don't overwrite SysBase under AmigaOS
|
||||
wp = (uint16 *)(ROMBaseHost + 0xccb4);
|
||||
*wp++ = htons(M68K_NOP);
|
||||
*wp = htons(M68K_NOP);
|
||||
#endif
|
||||
|
||||
#if REAL_ADDRESSING && !defined(AMIGA)
|
||||
#if REAL_ADDRESSING
|
||||
// gb-- Temporary hack to get rid of crashes in Speedometer
|
||||
wp = (uint16 *)(ROMBaseHost + 0xdba2);
|
||||
if (ntohs(*wp) == 0x662c) // bne.b #$2c
|
||||
*wp = htons(0x602c); // bra.b #$2c
|
||||
#endif
|
||||
|
||||
|
||||
// Don't write to VIA in InitTimeMgr
|
||||
wp = (uint16 *)(ROMBaseHost + 0xb0e2);
|
||||
*wp++ = htons(0x4cdf); // movem.l (sp)+,d0-d5/a0-a4
|
||||
|
|
|
@ -50,11 +50,7 @@ using std::vector;
|
|||
|
||||
|
||||
// Check for inserted disks by polling?
|
||||
#ifdef AMIGA
|
||||
#define DISK_INSERT_CHECK 1
|
||||
#else
|
||||
#define DISK_INSERT_CHECK 0
|
||||
#endif
|
||||
|
||||
|
||||
// Floppy disk icon
|
||||
|
|
|
@ -33,11 +33,7 @@
|
|||
#include "sysdeps.h"
|
||||
#include "user_strings.h"
|
||||
|
||||
#ifdef __BEOS__
|
||||
#define ELLIPSIS "\xE2\x80\xA6"
|
||||
#else
|
||||
#define ELLIPSIS "..."
|
||||
#endif
|
||||
|
||||
|
||||
// Common string definitions
|
||||
|
|
|
@ -59,9 +59,6 @@ links:
|
|||
include/prefs.h include/scsi.h include/serial.h \
|
||||
include/serial_defs.h include/sony.h include/sys.h \
|
||||
include/timer.h include/xpram.h \
|
||||
BeOS/audio_beos.cpp BeOS/extfs_beos.cpp BeOS/scsi_beos.cpp \
|
||||
BeOS/serial_beos.cpp BeOS/sys_beos.cpp BeOS/timer_beos.cpp \
|
||||
BeOS/xpram_beos.cpp BeOS/SheepDriver BeOS/SheepNet \
|
||||
CrossPlatform/sigsegv.h CrossPlatform/vm_alloc.h CrossPlatform/vm_alloc.cpp \
|
||||
CrossPlatform/video_vosf.h CrossPlatform/video_blit.h CrossPlatform/video_blit.cpp \
|
||||
Unix/audio_oss_esd.cpp \
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Acknowledgements</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Acknowledgements</H1>
|
||||
|
||||
The following persons/companies deserve special thanks from us as they
|
||||
made a significant contribution to the development of SheepShaver:
|
||||
|
||||
<P>
|
||||
<UL>
|
||||
<LI><A HREF="http://www.be.com/">Be Inc.</A>, and especially Dominic Giampaolo, for their support
|
||||
<LI>Tai Kahn from the <A HREF="http://www.ecafenet.com/">eCafe Network</A> for hosting the <A HREF="http://www.sheepshaver.com/">SheepShaver web site</A>
|
||||
<LI>Tinic Uro for the SheepShaver icon
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -1,47 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Contact Information</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Contact Information and Copyright</H1>
|
||||
|
||||
SheepShaver was brought to you by
|
||||
<UL>
|
||||
<LI><A HREF="mailto:Christian.Bauer@uni-mainz.de">Christian Bauer</A> (kernel, disk I/O)
|
||||
<LI><A HREF="mailto:Marc.Hellwig@uni-mainz.de">Marc Hellwig</A> (graphics, sound, networking)
|
||||
</UL>
|
||||
|
||||
<H3><IMG SRC="iconsmall.gif" ALIGN=MIDDLE>SheepShaver WWW Site:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<A HREF="http://www.sheepshaver.com/">www.sheepshaver.com</A><BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>EMail:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<A HREF="mailto:Christian.Bauer@uni-mainz.de">Christian.Bauer@uni-mainz.de</A><BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>License</H3>
|
||||
|
||||
<P>SheepShaver is available under the terms of the GNU General Public License.
|
||||
See the file "COPYING" that is included in the distribution for details.
|
||||
|
||||
<P>© Copyright 1997-2004 Christian Bauer and Marc Hellwig
|
||||
|
||||
<P>Names of hardware and software items mentioned in this manual and
|
||||
in program texts are in most cases registered trade marks of the respective
|
||||
companies and not marked as such. So the lack of such a note may not be
|
||||
used as an indication that these names are free.
|
||||
|
||||
<P>SheepShaver is not designed, intended, or authorized for use as a component
|
||||
in systems intended for surgical implant within the body, or other applications intended
|
||||
to support or sustain life, or for any other application in which the failure of SheepShaver
|
||||
could create a situation where personal injury or death may occur (so-called "killer application").
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB |
|
@ -1,59 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Revision History</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>SheepShaver Revision History</H1>
|
||||
|
||||
<H2>V2.2 (04-Feb-2002)</H2>
|
||||
<UL>
|
||||
<LI>Integrated code from Basilisk II
|
||||
<LI>Source released under GPL
|
||||
</UL>
|
||||
|
||||
<H2>V2.1 (31-Mar-2001)</H2>
|
||||
<UL>
|
||||
<LI>Support for MacOS 8.5 and 8.6
|
||||
<LI>Support for G3 ROMs
|
||||
<LI>It's possible to select which video modes are to be used by MacOS
|
||||
<LI>SheepShaver will not use up all CPU time when "nothing" is running
|
||||
<LI>More stable networking
|
||||
<LI>16 and 32 bit window modes
|
||||
<LI>Small bug fixes
|
||||
</UL>
|
||||
|
||||
<H2>V2.0 (20-Jan-1999)</H2>
|
||||
<UL>
|
||||
<LI>"BeOS" icon on the Mac desktop to access files on BeOS volumes from Mac applications.
|
||||
<LI>Handling of removable media (i.e. automatic detection of disk insertion)
|
||||
<LI>More flexible parallel port selection on BeBox
|
||||
<LI>Greatly improved Time Manager (higher accuracy)
|
||||
<LI>Fixed "audio lags"
|
||||
<LI>Option to ignore illegal memory accesses
|
||||
<LI>Adapted for (and requires) BeOS R4
|
||||
<LI>MacOS 7.5.5/7.6/7.6.1 run better on some systems
|
||||
<LI>Small bug fixes
|
||||
</UL>
|
||||
|
||||
<H2>V1.1 (13-Jul-1998)</H2>
|
||||
<UL>
|
||||
<LI>Support for more machine types (esp. PowerMac 4400)
|
||||
<LI>Corrected time zone handling
|
||||
<LI>Volume list in preferences handles dropped volumes and files
|
||||
<LI>BeBox: 16/24 bit modes have correct colors with a Millennium II
|
||||
<LI>Video/SetEntries didn't set last palette entry
|
||||
<LI>Mac programs trying to use the (non-existant) SCSI Manager shouldn't crash any longer
|
||||
</UL>
|
||||
|
||||
<H2>V1.0 (18-May-1998)</H2>
|
||||
<UL>
|
||||
<LI>Initial release
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
|
@ -1,28 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>The SheepShaver User's Guide</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1><IMG SRC="icon.gif" ALIGN=MIDDLE>SheepShaver V2.2 Installation and User's Guide (BeOS)</H1>
|
||||
|
||||
<H2>Contents</H2>
|
||||
|
||||
<UL>
|
||||
<LI><A HREF="introduction.html">Introduction</A>
|
||||
<LI><A HREF="installation.html">Installation</A>
|
||||
<LI><A HREF="quickstart.html">Quick Start</A>
|
||||
<LI><A HREF="settings.html">Setting up SheepShaver</A>
|
||||
<LI><A HREF="using.html">Using SheepShaver</A>
|
||||
<LI><A HREF="troubleshooting.html">Troubleshooting</A>
|
||||
<LI><A HREF="acknowledgements.html">Acknowledgements</A>
|
||||
<LI><A HREF="contact.html">Contact Information and Copyright</A>
|
||||
<LI><A HREF="history.html">Revision History</A>
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -1,25 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Installation</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Installation</H1>
|
||||
|
||||
You need BeOS/PowerPC R4. R3 or earlier versions will not work.
|
||||
|
||||
<OL>
|
||||
<LI>Unpack the SheepShaver package (if you are reading this, you probably have already done this)
|
||||
<LI>On a BeBox, you need a copy of a PCI PowerMac ROM (4MB) in a file
|
||||
called "ROM" in the same folder SheepShaver is in (but you can select a different
|
||||
location in the settings window). SheepShaver can also use the "Mac OS ROM" file
|
||||
that comes with MacOS 8.5/8.6 (look in the System Folder on your MacOS CD). In
|
||||
order to legally use SheepShaver, you have to own the ROM the image file was taken from.
|
||||
</OL>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -1,45 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Introduction</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Introduction</H1>
|
||||
|
||||
SheepShaver is a MacOS run-time environment for BeOS that allows you
|
||||
to run MacOS applications at native speed inside the BeOS multitasking
|
||||
environment on PowerPC-based BeOS systems. This means that both BeOS
|
||||
and MacOS applications can run at the same time and data can be exchanged
|
||||
between them.
|
||||
|
||||
<P>SheepShaver is neither a MacOS replacement nor an emulator. It runs an
|
||||
unmodified PowerPC MacOS under control of the BeOS at full speed without
|
||||
any kind of emulation. So it also uses the MacOS 68k emulator to run 68k
|
||||
applications. In this way, SheepShaver is comparable to the "Blue Box" of
|
||||
Apple's Rhapsody operating system.
|
||||
|
||||
<H2>Some of SheepShaver's features:</H2>
|
||||
|
||||
<UL>
|
||||
<LI>Compatibility: SheepShaver runs MacOS 7.5.2 thru 8.6 with all system
|
||||
extensions like AppleGuide, AppleScript, QuickTime, QuickTime VR,
|
||||
QuickDraw 3D, Open Transport, PPP, Language Kits, ColorSync, etc.
|
||||
<LI>Graphics: The MacOS user interface is displayed in a BeOS window or
|
||||
full-screen (with QuickDraw acceleration) in resolutions up to
|
||||
1600x1200 in 24 bit.
|
||||
<LI>Sound: CD-quality stereo sound output
|
||||
<LI>Networking: SheepShaver supports Internet and LAN networking via
|
||||
Ethernet and PPP with all Open Transport compatible MacOS applications.
|
||||
<LI>Volumes: Any HFS or HFS+ volume can be used with SheepShaver (this
|
||||
includes Zip/Jaz/SyQuest drives etc.). It also features a built-in
|
||||
CD-ROM driver and a driver for HD floppy disks.
|
||||
<LI>Data Exchange: You can access BeOS files from the MacOS via a "BeOS"
|
||||
icon on the Mac desktop and copy and paste text between BeOS and MacOS
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
Binary file not shown.
Before Width: | Height: | Size: 5.4 KiB |
|
@ -1,38 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Quick Start</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Quick Start</H1>
|
||||
|
||||
The following is a step-by-step guide that shows you how to get SheepShaver
|
||||
up and running in the quickest possible way. We assume that you are running
|
||||
on a PowerMac that already has MacOS installed on a partition of your hard drive
|
||||
and that you have booted into BeOS.
|
||||
|
||||
<P>
|
||||
<OL>
|
||||
<LI>Double-click the SheepShaver icon. The "SheepShaver Settings" window will appear.
|
||||
<LI>Click on "Start". SheepShaver will try to detect on which partition MacOS is installed and should then start booting MacOS.
|
||||
<LI>If this is the first time you start SheepShaver you will be asked if you want your
|
||||
network configuration to be modified to enable Ethernet networking under SheepShaver.
|
||||
If you want to use Ethernet with SheepShaver you should press "OK" (this will change the
|
||||
file <CODE>/boot/home/config/settings/network</CODE>; a backup of the the original file will
|
||||
be stored in <CODE>network.orig</CODE>).
|
||||
<LI>To quit SheepShaver, select "Shutdown" from the Finder's "Special" menu.
|
||||
</OL>
|
||||
|
||||
<H3>One word of caution:</H3>
|
||||
|
||||
Volumes which are used by SheepShaver must not also be mounted under BeOS
|
||||
while SheepShaver is running. <STRONG>You will lose data and corrupt the
|
||||
volume if you do this! Don't press the "Mount all disks now" button in the
|
||||
BeOS "Disk Mount Settings" window while SheepShaver is running!</STRONG>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
Binary file not shown.
Before Width: | Height: | Size: 4.7 KiB |
|
@ -1,127 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Setting up SheepShaver</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Setting up SheepShaver</H1>
|
||||
|
||||
In the "SheepShaver Settings" window that pops up when you double-click on
|
||||
the SheepShaver icon, you can configure certain features of SheepShaver.
|
||||
When you click on <B>"Start"</B>, the current settings are saved to disk and will be
|
||||
available next time you start SheepShaver.
|
||||
|
||||
<P>The settings are divided into four groups: Volumes, Graphics/Sound, Serial/Network and Memory/Misc.
|
||||
|
||||
<H2>Volumes</H2>
|
||||
|
||||
<IMG SRC="volumes.gif">
|
||||
|
||||
<P>The main part of the volumes pane is a <B>list</B> that contains all volumes to be mounted
|
||||
by SheepShaver. If this list is empty, SheepShaver will try to detect and mount all HFS partitions
|
||||
it can find. CD-ROM drives are always automatically detected and used.
|
||||
|
||||
<P>SheepShaver can use HFS partitions, whole HFS formatted drives, and it can also
|
||||
emulate hard disks in single BeOS files ("hardfiles").
|
||||
|
||||
<P>To add a Mac volume to the list, mount it on the BeOS side, click on <B>"Add..."</B>, go to the "Disks"
|
||||
level in the topmost popup menu of the file panel, click once on the volume you want and
|
||||
click on "Add". A line beginning with "/dev/disk/" should then appear in the volume list.
|
||||
After adding volumes to the list, you should unmount them on the BeOS side again.To remove
|
||||
a Mac volume, select it in the list and click on <B>"Remove"</B>.
|
||||
|
||||
<P>You can create a new, empty hardfile by clicking on <B>"Create..."</B>. Enter the file
|
||||
name and the size of the hardfile and click on "Create". The hardfile will be created (this may
|
||||
take some seconds) and added to the volume list. The so-created hardfile will have to be
|
||||
formatted under MacOS before you can store something in it. If you start up SheepShaver,
|
||||
the Finder will display a message about an "unreadable" volume being found and give you the
|
||||
option to format it.
|
||||
|
||||
<P>Double-clicking on an entry in the volume list will add or remove a "*" in front of the
|
||||
device name. Volumes marked with a "*" are read-only for the MacOS under SheepShaver.
|
||||
|
||||
<P>SheepShaver will show a "BeOS" disk icon on the Mac desktop that allows access to BeOS
|
||||
files from Mac applications. In <B>"BeOS Root"</B> you specify which BeOS directory will
|
||||
be at the root of this virtual "BeOS" disk. You can enter a path name here or drag and drop a
|
||||
Tracker folder onto it. The default setting of "/boot" means that the "BeOS" icon in the MacOS
|
||||
Finder will correspond to your BeOS boot volume. If you want to access files on other BeOS
|
||||
volumes, you should enter "/" here. The "BeOS" disk will then contain folders for each BeOS
|
||||
volume (among other things). The MacOS will create files and folders like "Desktop", "Trash",
|
||||
"OpenFolderListDF" etc. in the directory you specify as "BeOS Root". If they annoy you, you
|
||||
can delete them.
|
||||
|
||||
<P>To boot from CD-ROM, set the <B>"Boot From"</B> setting to <B>"CD-ROM"</B>.
|
||||
The <B>"Disable CD-ROM Driver"</B> box is used to disable SheepShaver's built-in CD-ROM driver.
|
||||
This is currently of not much use and you should leave the box unselected.
|
||||
|
||||
<H2>Graphics/Sound</H2>
|
||||
|
||||
<IMG SRC="graphics.gif">
|
||||
|
||||
<P>WIth <B>"Window Refresh Rate"</B> you can set the refresh rate of the MacOS window.
|
||||
Higher rates mean faster screen updates and less "sluggish" behaviour, but also require more CPU time.
|
||||
|
||||
<P>The <B>"QuickDraw Acceleration"</B> box should always be enabled. It allows for faster graphics in
|
||||
full-screen modes. But if your machine uses the "IXMicro" BeOS video driver, you have to disable the
|
||||
QuickDraw acceleration or full-screen modes won't work (this is because of BeOS bug #981112-032247).
|
||||
|
||||
<P>The main part of the window is occupied by a list of checkboxes that allows you to select
|
||||
which <B>graphics modes</B> are available for displaying the MacOS desktop. You can, for
|
||||
example, disable the modes that your monitor or graphics card can't display, or disable the
|
||||
window modes when you want to run some Mac programs in full-screen mode that would otherwise
|
||||
erroneously switch to a window mode. The actual mode to be used is selected in the "Monitors"
|
||||
control panel under MacOS.
|
||||
|
||||
<P>The <B>"Disable Sound Output"</B> box allows you to disable all sound output by SheepShaver.
|
||||
This is useful if the sound takes too much CPU time on your machine or to get rid of warning
|
||||
messages if SheepShaver can't use your audio hardware.
|
||||
|
||||
<H2>Serial/Network</H2>
|
||||
|
||||
<IMG SRC="serial.gif">
|
||||
|
||||
<P>You can select to which ports the MacOS <B>modem and printer ports</B> are redirected.
|
||||
This doesn't make much sense on a PowerMac, but on a BeBox you can assign the modem
|
||||
and printer ports to any of the four serial ports (or com3/com4) or even parallel ports of
|
||||
the BeBox (useful for printing if you have Mac drivers for parallel printers, like the PowerPrint
|
||||
package from <A HREF="http://www.gdt.com">www.gdt.com</A>).
|
||||
|
||||
<P>If you don't want SheepShaver's Ethernet support to be enabled for some reason, you
|
||||
can use the <B>"Disable Ethernet"</B> checkbox to disable it (this will also get rid of the annoying
|
||||
"no network hardware" messages if your Mac is not equipped with Ethernet).
|
||||
|
||||
<H2>Memory/Misc</H2>
|
||||
|
||||
<IMG SRC="memory.gif">
|
||||
|
||||
<P>With <B>"MacOS RAM Size"</B> you select how much RAM will be available to the MacOS
|
||||
(and all MacOS applications running under it). SheepShaver uses the BeOS virtual memory system,
|
||||
so you can select more RAM than you physically have in your machine. The MacOS virtual memory
|
||||
system is not available under SheepShaver (i.e. if you have 32MB of RAM in your computer and
|
||||
select 64MB to be used for MacOS in the SheepShaver settings, MacOS will behave as if it's running on
|
||||
a computer that has 64MB of RAM but no virtual memory).
|
||||
|
||||
<P>The <B>"Ignore Illegal Memory Accesses"</B> option is there to make some broken Mac
|
||||
programs work that access addresses where there is no RAM or ROM. With this option unchecked,
|
||||
SheepShaver will in this case display an error message and quit. When the option is activated,
|
||||
SheepShaver will try to continue as if the illegal access never happened (writes are ignored, reads
|
||||
return 0). This may or may not make the program work (when a program performs an illegal access,
|
||||
it is most likely that something else went wrong). When a Mac program behaves strangely or hangs,
|
||||
you can quit SheepShaver, uncheck this option and retry. If you get an "illegal access" message,
|
||||
you will know that something is broken.
|
||||
|
||||
<P>If the <B>"Don't Use CPU When Idle"</B> option is enabled, SheepShaver will try to reduce
|
||||
CPU usage to a minimum when the MacOS is doing "nothing" but waiting for user input. This doesn't
|
||||
work with all programs and it may confuse the timing of some games but in general you should
|
||||
leave it enabled.
|
||||
|
||||
<P><B>"ROM File"</B> specifies the path name of the Mac ROM file to be used. If it is left
|
||||
blank, SheepShaver expects the ROM file to be called "ROM" and be in the same directory as
|
||||
the SheepShaver application.
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -1,79 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Troubleshooting</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Troubleshooting</H1>
|
||||
|
||||
<H2>SheepShaver doesn't boot</H2>
|
||||
|
||||
SheepShaver should boot all MacOS versions >=7.5.2, except MacOS X. However,
|
||||
your mileage may vary. If it doesn't boot, try again with extensions disabled
|
||||
(by pressing the shift key) and then remove some of these extensions:
|
||||
"MacOS Licensing Extension", Speed Doubler, 68k FPU extensions and MacsBug.
|
||||
|
||||
<H2>The colors are wrong in 16 or 32 bit graphics modes</H2>
|
||||
|
||||
If you're running SheepShaver on a BeBox, the only graphics modes that have
|
||||
the right colors are the 8 bit modes (this is actually a hardware problem
|
||||
and has to do with frame buffers being little-endian on the BeBox), unless
|
||||
you are using a Matrox Milennium I/II.
|
||||
<P>You should also be aware that not all graphics cards support 16 bit modes
|
||||
under BeOS (especially S3 cards don't). Check the BeOS "Screen" preferences
|
||||
application to see if your card does.
|
||||
|
||||
<H2>SheepShaver appears to be very slow</H2>
|
||||
|
||||
<UL>
|
||||
<LI>Don't use the window modes, the fullscreen modes are much faster.
|
||||
<LI>If you nevertheless want (or have) to use a window mode, you should set the
|
||||
color depth in MacOS to the same as the BeOS workspace you are running SheepShaver on
|
||||
(e.g. if you are on a 16-bit workspace, set the color depth in MacOS to "Thousands").
|
||||
Also, set the window refresh rate to a low value (high values like 30Hz will make SheepShaver
|
||||
(and BeOS) slower, not faster!).
|
||||
</UL>
|
||||
|
||||
<H2>Full-screen mode doesn't work</H2>
|
||||
|
||||
If your machine uses the "IXMicro" BeOS video driver (TwinTurbo cards), you
|
||||
will have to disable the "QuickDraw Acceleration" in the "Video" pane of the
|
||||
SheepShaver settings.
|
||||
|
||||
<H2>Ethernet doesn't work</H2>
|
||||
|
||||
<UL>
|
||||
<LI>Is the Ethernet set up under BeOS? Ethernet will not work in SheepShaver if you didn't set it up in the BeOS "Network" preferences.
|
||||
<LI>If you're using TCP/IP on the MacOS side, you have to set up different IP addresses for the BeOS and for the MacOS.
|
||||
<LI>Try disabling AppleTalk in the BeOS Network preferences (there might be conflicts between BeOS AppleTalk and SheepShaver networking).
|
||||
</UL>
|
||||
|
||||
<H2>SheepShaver crashes, but yesterday it worked</H2>
|
||||
|
||||
Try the "Zap PRAM File" item in the main menu of the SheepShaver preferences editor.
|
||||
When you are using a ROM file and switching to a different ROM version, you <B>have</B>
|
||||
to zap the PRAM file or SheepShaver might behave very weird.
|
||||
|
||||
<H2>Known incompatibilities</H2>
|
||||
|
||||
<UL>
|
||||
<LI>MacOS programs or drivers which access Mac hardware directly are not supported by SheepShaver.
|
||||
<LI>Speed Doubler, RAM Doubler, 68k FPU emulators and similar programs don't run under SheepShaver.
|
||||
<LI>MacsBug is not compatible with SheepShaver.
|
||||
<LI>If you want to run RealPC on a BeBox, you have to disable one CPU in the "Pulse" application or it will crash.
|
||||
</UL>
|
||||
|
||||
<H2>Known bugs</H2>
|
||||
|
||||
<UL>
|
||||
<LI>The QuickTime 2.5 Cinepak codec crashes the emulator.
|
||||
<LI>Programs that use InputSprockets crash the emulator when in window mode.
|
||||
<LI>The mouse cursor hotspot in window mode is not correct.
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
|
@ -1,76 +0,0 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Using SheepShaver</TITLE>
|
||||
</HEAD>
|
||||
<BODY BGCOLOR=#FFFFFF>
|
||||
|
||||
<H1>Using SheepShaver</H1>
|
||||
|
||||
<H2>Changing the display mode</H2>
|
||||
|
||||
SheepShaver can display the MacOS user interface in a BeOS window or full-screen
|
||||
(much faster) in several resolutions and color depths. You select the display mode
|
||||
as usual under MacOS in the "Monitors" control panel (under System 7.x, click on "Options").
|
||||
The "75Hz" modes are full-screen modes, the "60Hz" modes are window modes
|
||||
(this doesn't mean that the video refresh rate is 75 or 60Hz in the respective modes;
|
||||
the rate displayed has no meaning; it's simply there to distinguish full screen modes
|
||||
from window modes).
|
||||
|
||||
<H2>Window mode</H2>
|
||||
|
||||
The SheepShaver window has a menu at the bottom that allows you to change the
|
||||
graphics refresh rate and to mount floppy disks (see below). The window refresh is
|
||||
disabled as long as the "Scroll Lock" key is pressed (the graphics output is then frozen).
|
||||
|
||||
<H2>Full-screen mode</H2>
|
||||
|
||||
The full-screen mode uses a whole BeOS workspace for displaying the MacOS user
|
||||
interface. You can switch workspaces with Command-F1/F2/F3/etc. Please note that
|
||||
the MacOS (and all MacOS applications) will be suspended when you switch to a different
|
||||
workspace. It will only be resumed when you go back to the SheepShaver workspace.
|
||||
|
||||
<H2>Networking</H2>
|
||||
|
||||
SheepShaver only supports Ethernet networking (and PPP via the serial
|
||||
ports). If there are multiple Ethernet cards installed, only the first
|
||||
card will be used. The Ethernet support is implemented at the data-link
|
||||
level. This implies that the "Mac" and the "Be" side must have two different
|
||||
network addresses.
|
||||
|
||||
<H2>Using floppy disks</H2>
|
||||
|
||||
Floppy disks are not automatically detected when they are inserted. They have to be
|
||||
mounted explicitly. After inserting a floppy disk, select the "Mount Floppy" item in the
|
||||
"SheepShaver" menu (when running in window mode), or press Ctrl-F1 (when running in
|
||||
full-screen mode). BeBox users should note that floppy disks also have to be unmounted
|
||||
under MacOS before ejecting them from the drive.
|
||||
|
||||
<H2>Accessing BeOS files</H2>
|
||||
|
||||
SheepShaver will display a "BeOS" disk icon on the Mac desktop that allows you
|
||||
to access any BeOS files/folders which are in the directory specified as "BeOS Root"
|
||||
in the "Volumes" pane of the SheepShaver settings. You can open and save files on the
|
||||
"BeOS" disk from Mac applications, copy, move or rename files from the Finder etc.
|
||||
Putting files/folder to the trash may however not always work. SheepShaver translates
|
||||
some BeOS file types to MacOS types and vice versa, so e.g. JPEG and PDF files will
|
||||
show up the correct icons in the Finder. To store Mac resources and other additional
|
||||
data, SheepShaver uses the following BeOS file attributes:
|
||||
|
||||
<UL>
|
||||
<LI><CODE>MACOS:RFORK</CODE> contains the complete Mac resource fork of the file
|
||||
<LI><CODE>MACOS:HFS_FLAGS</CODE> contains Finder flags
|
||||
<LI><CODE>MACOS:CREATOR</CODE> contains the MacOS creator application ID
|
||||
</UL>
|
||||
|
||||
<H2>Copying text via the clipboard</H2>
|
||||
|
||||
SheepShaver tries to keep the BeOS and MacOS clipboards synchronized. That means,
|
||||
when you copy a piece of text under BeOS, you can paste it into a MacOS application
|
||||
and vice versa.
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
SheepShaver User's Guide
|
||||
</ADDRESS>
|
||||
</BODY>
|
||||
</HTML>
|
Binary file not shown.
Before Width: | Height: | Size: 7.3 KiB |
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
* Ethernet.cpp - SheepShaver ethernet PCI driver stub
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include <stddef.h>
|
||||
#include "xlowmem.h"
|
||||
#include "ether_defs.h"
|
||||
|
||||
|
||||
/*
|
||||
* Driver Description structure
|
||||
*/
|
||||
|
||||
struct DriverDescription {
|
||||
uint32 driverDescSignature;
|
||||
uint32 driverDescVersion;
|
||||
char nameInfoStr[32];
|
||||
uint32 version;
|
||||
uint32 driverRuntime;
|
||||
char driverName[32];
|
||||
uint32 driverDescReserved[8];
|
||||
uint32 nServices;
|
||||
uint32 serviceCategory;
|
||||
uint32 serviceType;
|
||||
uint32 serviceVersion;
|
||||
};
|
||||
|
||||
#pragma export on
|
||||
DriverDescription TheDriverDescription = {
|
||||
'mtej',
|
||||
0,
|
||||
"\pSheepShaver Ethernet",
|
||||
0x01008000, // V1.0.0final
|
||||
4, // kDriverIsUnderExpertControl
|
||||
"\penet",
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1,
|
||||
'otan',
|
||||
0x000a0b01, // Ethernet, Framing: Ethernet/EthernetIPX/802.2, IsDLPI
|
||||
0x01000000, // V1.0.0
|
||||
};
|
||||
#pragma export off
|
||||
|
||||
|
||||
/*
|
||||
* install_info and related structures
|
||||
*/
|
||||
|
||||
static int ether_open(queue_t *rdq, void *dev, int flag, int sflag, void *creds);
|
||||
static int ether_close(queue_t *rdq, int flag, void *creds);
|
||||
static int ether_wput(queue_t *q, msgb *mp);
|
||||
static int ether_wsrv(queue_t *q);
|
||||
static int ether_rput(queue_t *q, msgb *mp);
|
||||
static int ether_rsrv(queue_t *q);
|
||||
|
||||
struct ot_module_info {
|
||||
uint16 mi_idnum;
|
||||
char *mi_idname;
|
||||
int32 mi_minpsz; // Minimum packet size
|
||||
int32 mi_maxpsz; // Maximum packet size
|
||||
uint32 mi_hiwat; // Queue hi-water mark
|
||||
uint32 mi_lowat; // Queue lo-water mark
|
||||
};
|
||||
|
||||
static ot_module_info module_information = {
|
||||
kEnetModuleID,
|
||||
"SheepShaver Ethernet",
|
||||
0,
|
||||
kEnetTSDU,
|
||||
6000,
|
||||
5000
|
||||
};
|
||||
|
||||
typedef int (*putp_t)(queue_t *, msgb *);
|
||||
typedef int (*srvp_t)(queue_t *);
|
||||
typedef int (*openp_t)(queue_t *, void *, int, int, void *);
|
||||
typedef int (*closep_t)(queue_t *, int, void *);
|
||||
|
||||
struct qinit {
|
||||
putp_t qi_putp;
|
||||
srvp_t qi_srvp;
|
||||
openp_t qi_qopen;
|
||||
closep_t qi_qclose;
|
||||
void *qi_qadmin;
|
||||
struct ot_module_info *qi_minfo;
|
||||
void *qi_mstat;
|
||||
};
|
||||
|
||||
static qinit read_side = {
|
||||
NULL,
|
||||
ether_rsrv,
|
||||
ether_open,
|
||||
ether_close,
|
||||
NULL,
|
||||
&module_information,
|
||||
NULL
|
||||
};
|
||||
|
||||
static qinit write_side = {
|
||||
ether_wput,
|
||||
NULL,
|
||||
ether_open,
|
||||
ether_close,
|
||||
NULL,
|
||||
&module_information,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct streamtab {
|
||||
struct qinit *st_rdinit;
|
||||
struct qinit *st_wrinit;
|
||||
struct qinit *st_muxrinit;
|
||||
struct qinit *st_muxwinit;
|
||||
};
|
||||
|
||||
static streamtab the_streamtab = {
|
||||
&read_side,
|
||||
&write_side,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct install_info {
|
||||
struct streamtab *install_str;
|
||||
uint32 install_flags;
|
||||
uint32 install_sqlvl;
|
||||
char *install_buddy;
|
||||
void *ref_load;
|
||||
uint32 ref_count;
|
||||
};
|
||||
|
||||
enum {
|
||||
kOTModIsDriver = 0x00000001,
|
||||
kOTModUpperIsDLPI = 0x00002000,
|
||||
SQLVL_MODULE = 3,
|
||||
};
|
||||
|
||||
static install_info the_install_info = {
|
||||
&the_streamtab,
|
||||
kOTModIsDriver /*| kOTModUpperIsDLPI */,
|
||||
SQLVL_MODULE,
|
||||
NULL,
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
// Prototypes for exported functions
|
||||
extern "C" {
|
||||
#pragma export on
|
||||
extern uint32 ValidateHardware(void *theID);
|
||||
extern install_info* GetOTInstallInfo();
|
||||
extern uint8 InitStreamModule(void *theID);
|
||||
extern void TerminateStreamModule(void);
|
||||
#pragma export off
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Validate that our hardware is available (always available)
|
||||
*/
|
||||
|
||||
uint32 ValidateHardware(void *theID)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return pointer to install_info structure
|
||||
*/
|
||||
|
||||
install_info *GetOTInstallInfo(void)
|
||||
{
|
||||
return &the_install_info;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Init module
|
||||
*/
|
||||
|
||||
asm uint8 InitStreamModule(register void *theID)
|
||||
{
|
||||
lwz r2,XLM_TOC
|
||||
lwz r0,XLM_ETHER_INIT
|
||||
mtctr r0
|
||||
bctr
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Terminate module
|
||||
*/
|
||||
|
||||
asm void TerminateStreamModule(void)
|
||||
{
|
||||
lwz r2,XLM_TOC
|
||||
lwz r0,XLM_ETHER_TERM
|
||||
mtctr r0
|
||||
bctr
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DLPI functions
|
||||
*/
|
||||
|
||||
static asm int ether_open(register queue_t *rdq, register void *dev, register int flag, register int sflag, register void *creds)
|
||||
{
|
||||
lwz r2,XLM_TOC
|
||||
lwz r0,XLM_ETHER_OPEN
|
||||
mtctr r0
|
||||
bctr
|
||||
}
|
||||
|
||||
static asm int ether_close(register queue_t *rdq, register int flag, register void *creds)
|
||||
{
|
||||
lwz r2,XLM_TOC
|
||||
lwz r0,XLM_ETHER_CLOSE
|
||||
mtctr r0
|
||||
bctr
|
||||
}
|
||||
|
||||
static asm int ether_wput(register queue_t *q, register msgb *mp)
|
||||
{
|
||||
lwz r2,XLM_TOC
|
||||
lwz r0,XLM_ETHER_WPUT
|
||||
mtctr r0
|
||||
bctr
|
||||
}
|
||||
|
||||
static asm int ether_rsrv(register queue_t *q)
|
||||
{
|
||||
lwz r2,XLM_TOC
|
||||
lwz r0,XLM_ETHER_RSRV
|
||||
mtctr r0
|
||||
bctr
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
all: ../../EthernetDriverStub.i ../../VideoDriverStub.i
|
||||
|
||||
clean:
|
||||
-rm *.o hexconv Ethernet Video
|
||||
|
||||
../../EthernetDriverStub.i: Ethernet hexconv
|
||||
hexconv $< $@
|
||||
|
||||
../../VideoDriverStub.i: Video hexconv
|
||||
hexconv $< $@
|
||||
|
||||
hexconv: hexconv.cpp
|
||||
mwcc -o hexconv hexconv.cpp
|
||||
|
||||
Ethernet.o: Ethernet.cpp
|
||||
mwcc -I.. -I../../include -o $@ -c $<
|
||||
|
||||
Video.o: Video.cpp
|
||||
mwcc -I.. -I../../include -o $@ -c $<
|
||||
|
||||
Ethernet: Ethernet.o
|
||||
mwldppc -xms -export pragma -nostdentry -nostdlib -o $@ $<
|
||||
|
||||
Video: Video.o
|
||||
mwldppc -xms -export pragma -nostdentry -nostdlib -o $@ $<
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Video.cpp - SheepShaver video PCI driver stub
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "xlowmem.h"
|
||||
|
||||
|
||||
/*
|
||||
* Driver Description structure
|
||||
*/
|
||||
|
||||
struct DriverDescription {
|
||||
uint32 driverDescSignature;
|
||||
uint32 driverDescVersion;
|
||||
char nameInfoStr[32];
|
||||
uint32 version;
|
||||
uint32 driverRuntime;
|
||||
char driverName[32];
|
||||
uint32 driverDescReserved[8];
|
||||
uint32 nServices;
|
||||
uint32 serviceCategory;
|
||||
uint32 serviceType;
|
||||
uint32 serviceVersion;
|
||||
};
|
||||
|
||||
#pragma export on
|
||||
struct DriverDescription TheDriverDescription = {
|
||||
'mtej',
|
||||
0,
|
||||
"\pvideo",
|
||||
0x01008000, // V1.0.0final
|
||||
6, // kDriverIsUnderExpertControl, kDriverIsOpenedUponLoad
|
||||
"\pDisplay_Video_Apple_Sheep",
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1,
|
||||
'ndrv',
|
||||
'vido',
|
||||
0x01000000, // V1.0.0
|
||||
};
|
||||
#pragma export off
|
||||
|
||||
|
||||
// Prototypes for exported functions
|
||||
extern "C" {
|
||||
#pragma export on
|
||||
extern int16 DoDriverIO(void *spaceID, void *commandID, void *commandContents, uint32 commandCode, uint32 commandKind);
|
||||
#pragma export off
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do driver IO
|
||||
*/
|
||||
|
||||
asm int16 DoDriverIO(void *spaceID, void *commandID, void *commandContents, uint32 commandCode, uint32 commandKind)
|
||||
{
|
||||
lwz r2,XLM_TOC
|
||||
lwz r0,XLM_VIDEO_DOIO
|
||||
mtctr r0
|
||||
bctr
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
printf("Usage: %s <raw file> <C source>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *fin = fopen(argv[1], "rb");
|
||||
if (fin == NULL) {
|
||||
printf("Can't open '%s' for reading\n", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *fout = fopen(argv[2], "w");
|
||||
if (fout == NULL) {
|
||||
printf("Can't open '%s' for writing\n", argv[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char buf[16];
|
||||
while (!feof(fin)) {
|
||||
fprintf(fout, "\t");
|
||||
int actual = fread(buf, 1, 16, fin);
|
||||
for (int i=0; i<actual; i++)
|
||||
fprintf(fout, "0x%02x, ", buf[i]);
|
||||
fprintf(fout, "\n");
|
||||
}
|
||||
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
return 0;
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
## BeOS Generic Makefile v2.1 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME= SheepShaver
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE= APP
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
SRCS= ../main.cpp main_beos.cpp ../prefs.cpp ../prefs_items.cpp prefs_beos.cpp \
|
||||
prefs_editor_beos.cpp sys_beos.cpp ../rom_patches.cpp ../rsrc_patches.cpp \
|
||||
../emul_op.cpp ../name_registry.cpp ../macos_util.cpp ../timer.cpp \
|
||||
timer_beos.cpp ../xpram.cpp xpram_beos.cpp ../adb.cpp clip_beos.cpp \
|
||||
../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp scsi_beos.cpp \
|
||||
../video.cpp video_beos.cpp ../audio.cpp audio_beos.cpp ../ether.cpp \
|
||||
ether_beos.cpp ../serial.cpp serial_beos.cpp ../extfs.cpp extfs_beos.cpp \
|
||||
about_window_beos.cpp ../user_strings.cpp user_strings_beos.cpp ../thunks.cpp
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS= SheepShaver.rsrc
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS= be tracker game media translation textencoding device GL
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS=
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS =
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS = ../include SheepDriver SheepNet
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
OPTIMIZE= FULL
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES=
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS =
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS =
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from a source-level
|
||||
# debugger. Note that this will disable all optimzation.
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS = -prefix BeHeaders
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
|
||||
## include the makefile-engine
|
||||
include /boot/develop/etc/makefile-engine
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
## BeOS Generic Makefile v2.1 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME= NetPeek
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE= APP
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
SRCS= NetPeek.cpp
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS=
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS=
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS=
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS =
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS = ../ ../../include ../NetAddOn
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
OPTIMIZE= FULL
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES=
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS =
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS =
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from a source-level
|
||||
# debugger. Note that this will disable all optimzation.
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS =
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
|
||||
## include the makefile-engine
|
||||
include /boot/develop/etc/makefile-engine
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* NetPeek.cpp - Utility program for monitoring SheepNet add-on
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "sheep_net.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static area_id buffer_area; // Packet buffer area
|
||||
static net_buffer *net_buffer_ptr; // Pointer to packet buffer
|
||||
|
||||
int main(void)
|
||||
{
|
||||
area_id handler_buffer;
|
||||
if ((handler_buffer = find_area("packet buffer")) < B_NO_ERROR) {
|
||||
printf("Can't find packet buffer\n");
|
||||
return 10;
|
||||
}
|
||||
if ((buffer_area = clone_area("local packet buffer", &net_buffer_ptr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, handler_buffer)) < B_NO_ERROR) {
|
||||
printf("Can't clone packet buffer\n");
|
||||
return 10;
|
||||
}
|
||||
|
||||
uint8 *p = net_buffer_ptr->ether_addr;
|
||||
printf("Ethernet address : %02x %02x %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
printf("read_sem : %d\n", net_buffer_ptr->read_sem);
|
||||
printf("read_ofs : %d\n", net_buffer_ptr->read_ofs);
|
||||
printf("read_packet_size : %d\n", net_buffer_ptr->read_packet_size);
|
||||
printf("read_packet_count : %d\n", net_buffer_ptr->read_packet_count);
|
||||
printf("write_sem : %d\n", net_buffer_ptr->write_sem);
|
||||
printf("write_ofs : %d\n", net_buffer_ptr->write_ofs);
|
||||
printf("write_packet_size : %d\n", net_buffer_ptr->write_packet_size);
|
||||
printf("write_packet_count: %d\n", net_buffer_ptr->write_packet_count);
|
||||
|
||||
printf("\nRead packets:\n");
|
||||
for (int i=0; i<READ_PACKET_COUNT; i++) {
|
||||
net_packet *p = &net_buffer_ptr->read[i];
|
||||
printf("cmd : %08lx\n", p->cmd);
|
||||
printf("length: %d\n", p->length);
|
||||
}
|
||||
printf("\nWrite packets:\n");
|
||||
for (int i=0; i<WRITE_PACKET_COUNT; i++) {
|
||||
net_packet *p = &net_buffer_ptr->write[i];
|
||||
printf("cmd : %08lx\n", p->cmd);
|
||||
printf("length: %d\n", p->length);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
## BeOS Generic Makefile v2.1 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME= SaveROM
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE= APP
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
SRCS= SaveROM.cpp
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS= SaveROM.rsrc
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS= be
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS=
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS =
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS = ../ ../../include ../NetAddOn
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
OPTIMIZE= FULL
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES=
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS =
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS =
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from a source-level
|
||||
# debugger. Note that this will disable all optimzation.
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS =
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
|
||||
## include the makefile-engine
|
||||
include /boot/develop/etc/makefile-engine
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
"SaveROM" is a program that allows you to save the ROM of
|
||||
a PowerMac running under BeOS to a file.
|
||||
|
||||
1. Copy "sheep_driver" to ~/config/add-ons/kernel/drivers.
|
||||
2. Double-click the "SaveROM" icon.
|
||||
|
||||
This will create a file called "ROM" which should be 4MB
|
||||
in size.
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* SaveROM - Save Mac ROM to file
|
||||
*
|
||||
* Copyright (C) 1998-2004 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <AppKit.h>
|
||||
#include <InterfaceKit.h>
|
||||
#include <StorageKit.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
// Constants
|
||||
const char APP_SIGNATURE[] = "application/x-vnd.cebix-SaveROM";
|
||||
const char ROM_FILE_NAME[] = "ROM";
|
||||
|
||||
// Global variables
|
||||
static uint8 buf[0x400000];
|
||||
|
||||
// Application object
|
||||
class SaveROM : public BApplication {
|
||||
public:
|
||||
SaveROM() : BApplication(APP_SIGNATURE)
|
||||
{
|
||||
// Find application directory and cwd to it
|
||||
app_info the_info;
|
||||
GetAppInfo(&the_info);
|
||||
BEntry the_file(&the_info.ref);
|
||||
BEntry the_dir;
|
||||
the_file.GetParent(&the_dir);
|
||||
BPath the_path;
|
||||
the_dir.GetPath(&the_path);
|
||||
chdir(the_path.Path());
|
||||
}
|
||||
virtual void ReadyToRun(void);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Create application object and start it
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
SaveROM *the_app = new SaveROM();
|
||||
the_app->Run();
|
||||
delete the_app;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display error alert
|
||||
*/
|
||||
|
||||
static void ErrorAlert(const char *text)
|
||||
{
|
||||
BAlert *alert = new BAlert("SaveROM Error", text, "Quit", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
|
||||
alert->Go();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Display OK alert
|
||||
*/
|
||||
|
||||
static void InfoAlert(const char *text)
|
||||
{
|
||||
BAlert *alert = new BAlert("SaveROM Message", text, "Quit", NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT);
|
||||
alert->Go();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main program
|
||||
*/
|
||||
|
||||
void SaveROM::ReadyToRun(void)
|
||||
{
|
||||
int fd = open("/dev/sheep", 0);
|
||||
if (fd < 0) {
|
||||
ErrorAlert("Cannot open '/dev/sheep'.");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (read(fd, buf, 0x400000) != 0x400000) {
|
||||
ErrorAlert("Cannot read ROM.");
|
||||
close(fd);
|
||||
goto done;
|
||||
}
|
||||
|
||||
FILE *f = fopen(ROM_FILE_NAME, "wb");
|
||||
if (f == NULL) {
|
||||
ErrorAlert("Cannot open ROM file.");
|
||||
close(fd);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fwrite(buf, 1, 0x400000, f) != 0x400000) {
|
||||
ErrorAlert("Cannot write ROM.");
|
||||
fclose(f);
|
||||
close(fd);
|
||||
goto done;
|
||||
}
|
||||
|
||||
InfoAlert("ROM saved.");
|
||||
|
||||
fclose(f);
|
||||
close(fd);
|
||||
done:
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
../../../BasiliskII/src/BeOS/SheepDriver
|
|
@ -1 +0,0 @@
|
|||
../../../BasiliskII/src/BeOS/SheepNet
|
Binary file not shown.
|
@ -1,289 +0,0 @@
|
|||
/*
|
||||
* about_window_beos.cpp - "About" window, BeOS implementation
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <GLView.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "about_window.h"
|
||||
#include "video.h"
|
||||
#include "version.h"
|
||||
#include "user_strings.h"
|
||||
|
||||
|
||||
// About window dimensions
|
||||
static const BRect about_frame = BRect(0, 0, 383, 99);
|
||||
|
||||
// Special colors
|
||||
const rgb_color fill_color = {216, 216, 216, 0};
|
||||
|
||||
// SheepShaver icon
|
||||
static const uint8 sheep_icon[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xda, 0x15, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xff, 0x00, 0x00, 0x00, 0x16, 0xda, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16,
|
||||
0x00, 0x1d, 0xda, 0x1e, 0x1e, 0x1e, 0xda, 0x16, 0x00, 0x00, 0x16, 0xda, 0x16, 0xda, 0x08, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x00, 0x00, 0x00, 0x0b, 0xff, 0xff, 0x11, 0x00, 0xda,
|
||||
0x1d, 0xda, 0x1e, 0xda, 0x1e, 0xda, 0x1e, 0xda, 0x1e, 0x16, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff,
|
||||
0xff, 0x0b, 0x00, 0x00, 0x16, 0x16, 0x00, 0x12, 0xfd, 0x1d, 0x0b, 0x00, 0x00, 0x1d, 0xfd, 0x1d,
|
||||
0xfd, 0x1e, 0xda, 0x1e, 0xda, 0x1e, 0xda, 0x3f, 0xda, 0x3f, 0xda, 0x15, 0x00, 0xff, 0xff, 0xff,
|
||||
0x16, 0x00, 0x17, 0x16, 0x00, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x16, 0x0f, 0x0b, 0x1d,
|
||||
0x1e, 0xfd, 0x1e, 0xda, 0x1e, 0xda, 0x3f, 0xda, 0x3f, 0xda, 0x1d, 0x5a, 0x15, 0xff, 0xff, 0xff,
|
||||
0x05, 0x17, 0x16, 0x00, 0x12, 0x1d, 0x00, 0x1d, 0xfd, 0x00, 0xfd, 0x00, 0x00, 0x16, 0x0b, 0x00,
|
||||
0x00, 0x0e, 0x1d, 0x3f, 0xda, 0x3f, 0xda, 0x1d, 0xda, 0x1b, 0x5a, 0x1b, 0x0f, 0x1d, 0xff, 0xff,
|
||||
0xff, 0x05, 0x00, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x1a, 0xfd, 0x00, 0x0f, 0x14, 0x14,
|
||||
0x16, 0x00, 0x15, 0xfd, 0x1d, 0xda, 0x1b, 0xda, 0x1b, 0x5a, 0x1b, 0x5a, 0x0f, 0x14, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x1a, 0xfd, 0x12, 0x00, 0x16, 0x00, 0x0f,
|
||||
0x00, 0x1b, 0xfd, 0x1e, 0xfd, 0x1b, 0xda, 0x1b, 0x5a, 0x1b, 0x5a, 0x1b, 0x5a, 0x14, 0xff, 0xff,
|
||||
0xff, 0x00, 0x1d, 0xfd, 0x1d, 0xfd, 0x1d, 0xfd, 0x1a, 0xfd, 0x12, 0x00, 0x16, 0x1b, 0x16, 0x0e,
|
||||
0x1b, 0xfd, 0x1b, 0xfd, 0x1b, 0xfd, 0x1b, 0x5a, 0x18, 0x00, 0x00, 0x5a, 0x1b, 0x00, 0xff, 0xff,
|
||||
0xff, 0x00, 0xfd, 0x14, 0xfd, 0x14, 0xfd, 0x1d, 0xfd, 0x12, 0x00, 0x16, 0xfd, 0x1b, 0xfd, 0x1b,
|
||||
0xfd, 0x1b, 0xfd, 0x1e, 0xfd, 0x1b, 0x5a, 0x18, 0x5a, 0x00, 0x00, 0x1b, 0x9b, 0x00, 0xff, 0xff,
|
||||
0xff, 0x00, 0x0f, 0xfd, 0x1d, 0xfd, 0x0f, 0xfd, 0x12, 0x00, 0x16, 0xfd, 0x1b, 0xfd, 0x1b, 0xfd,
|
||||
0x1b, 0xfd, 0x18, 0xfd, 0x1b, 0xf9, 0x18, 0x5a, 0x00, 0x12, 0x00, 0x9b, 0x1b, 0x00, 0xff, 0xff,
|
||||
0xff, 0x00, 0xfd, 0x0a, 0x0a, 0x0a, 0xfd, 0x10, 0x00, 0x1b, 0xfd, 0x1b, 0xfd, 0x1b, 0xfd, 0x18,
|
||||
0xfd, 0x15, 0xfa, 0x15, 0xf9, 0x18, 0x15, 0x00, 0x12, 0x9b, 0x00, 0x1b, 0x9b, 0x00, 0x15, 0x15,
|
||||
0xff, 0xff, 0x00, 0xfd, 0x1d, 0xfd, 0x1d, 0x00, 0x16, 0x00, 0x1b, 0xfd, 0x1b, 0xfd, 0x15, 0xfd,
|
||||
0x15, 0xfa, 0x15, 0xf9, 0x15, 0x16, 0x00, 0x0f, 0x9b, 0x12, 0x00, 0x9b, 0x1b, 0x00, 0x15, 0x15,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x1d, 0x00, 0xfa, 0x1e, 0x00, 0x1e, 0xfa, 0x15,
|
||||
0xfa, 0x15, 0x16, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x12, 0x15, 0x15,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1d, 0xf9, 0x00, 0x3f, 0xfa, 0x00, 0xfa, 0x1b, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x00, 0x00, 0x12, 0x15, 0x15, 0x15, 0x15,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf9, 0x1d, 0x00, 0xf9, 0x1b, 0x00, 0x1b, 0xf9, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1d, 0xf9, 0x00, 0x3f, 0xf9, 0x00, 0xf9, 0x1b, 0x00,
|
||||
0xff, 0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x16, 0x1d, 0x00, 0xf9, 0x1b, 0x00, 0x1b, 0xf9, 0x00,
|
||||
0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x00, 0x00, 0x00, 0x16, 0xf9, 0x00, 0x1b, 0x16, 0x00,
|
||||
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
|
||||
0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x15, 0x00, 0x0a, 0x19, 0x0a, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x00, 0x16, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x19, 0x1c, 0x18, 0x00, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
|
||||
0x0f, 0xff, 0xff, 0xff, 0x00, 0x18, 0x11, 0x00, 0x15, 0x00, 0x1c, 0x18, 0x00, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x00, 0x00, 0x00, 0x0b, 0x0b,
|
||||
0x00, 0x00, 0x0f, 0xff, 0x12, 0x00, 0x18, 0x19, 0x00, 0x15, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x00, 0x00, 0x14, 0x1e, 0xfd, 0x01, 0xfd, 0x14,
|
||||
0xfa, 0xf9, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x19, 0x1c, 0x00, 0x18, 0x1c, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x14, 0xfd, 0x1e, 0xf9, 0x1e, 0xfa, 0x1e, 0xf9,
|
||||
0x14, 0xfa, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x18, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x14, 0x1e, 0xf9, 0x14, 0xfa, 0x1e, 0xf9, 0x1e,
|
||||
0xfd, 0x1e, 0x00, 0x15, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0x00, 0x00, 0x18, 0x00, 0x1c, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0x00, 0xfd, 0x1e, 0xfd, 0x14, 0xfd, 0x1e, 0xfd,
|
||||
0x1e, 0x01, 0x00, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x00, 0x00, 0x1c, 0x00, 0x15,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x14, 0xfa, 0x01, 0xf9, 0x1e, 0xf9, 0x14,
|
||||
0x14, 0x00, 0x0f, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x00, 0x00, 0x15, 0x15,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0f, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
|
||||
0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
|
||||
// View class
|
||||
class AboutViewT : public BView {
|
||||
public:
|
||||
AboutViewT(BRect r) : BView(r, "", B_FOLLOW_NONE, B_WILL_DRAW) {}
|
||||
|
||||
virtual void Draw(BRect update)
|
||||
{
|
||||
char str[256];
|
||||
sprintf(str, GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
|
||||
|
||||
SetFont(be_bold_font);
|
||||
SetDrawingMode(B_OP_OVER);
|
||||
MovePenTo(20, 20);
|
||||
DrawString(str);
|
||||
SetFont(be_plain_font);
|
||||
MovePenTo(20, 40);
|
||||
DrawString(GetString(STR_ABOUT_TEXT2));
|
||||
MovePenTo(20, 60);
|
||||
DrawString(B_UTF8_COPYRIGHT "1997-2008 Christian Bauer and Marc Hellwig");
|
||||
}
|
||||
|
||||
virtual void MouseDown(BPoint point)
|
||||
{
|
||||
Window()->PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 3D view class
|
||||
class AboutView3D : public BGLView {
|
||||
public:
|
||||
AboutView3D(BRect r) : BGLView(r, "", B_FOLLOW_NONE, 0, BGL_RGB | BGL_DOUBLE)
|
||||
{
|
||||
rot_x = rot_y = 0;
|
||||
|
||||
if (!VideoSnapshot(64, 64, texture)) {
|
||||
uint8 *p = texture;
|
||||
const uint8 *q = sheep_icon;
|
||||
const color_map *cm = system_colors();
|
||||
for (int i=0; i<32*32; i++) {
|
||||
uint8 red = cm->color_list[*q].red;
|
||||
uint8 green = cm->color_list[*q].green;
|
||||
uint8 blue = cm->color_list[*q++].blue;
|
||||
p[0] = p[3] = p[64*3] = p[65*3] = red;
|
||||
p[1] = p[4] = p[64*3+1] = p[65*3+1] = green;
|
||||
p[2] = p[5] = p[64*3+2] = p[65*3+2] = blue;
|
||||
p += 6;
|
||||
if ((i & 31) == 31)
|
||||
p += 64*3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void AttachedToWindow(void)
|
||||
{
|
||||
BGLView::AttachedToWindow();
|
||||
LockGL();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(30, 1, 0.5, 20);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
GLfloat light_color[4] = {1, 1, 1, 1};
|
||||
GLfloat light_dir[4] = {1, 2, 1.5, 1};
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light_dir);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
UnlockGL();
|
||||
|
||||
tick_thread_active = true;
|
||||
tick_thread = spawn_thread(tick_func, "OpenGL Animation", B_NORMAL_PRIORITY, this);
|
||||
resume_thread(tick_thread);
|
||||
}
|
||||
|
||||
virtual void DetachedFromWindow(void)
|
||||
{
|
||||
status_t l;
|
||||
tick_thread_active = false;
|
||||
wait_for_thread(tick_thread, &l);
|
||||
|
||||
BGLView::DetachedFromWindow();
|
||||
}
|
||||
|
||||
virtual void Draw(BRect update)
|
||||
{
|
||||
LockGL();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBegin(GL_QUADS);
|
||||
glNormal3d(0, 0, 1);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3d(-1, 1, 0);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex3d(1, 1, 0);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3d(1, -1, 0);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex3d(-1, -1, 0);
|
||||
glEnd();
|
||||
SwapBuffers();
|
||||
UnlockGL();
|
||||
}
|
||||
|
||||
static status_t tick_func(void *arg)
|
||||
{
|
||||
AboutView3D *obj = (AboutView3D *)arg;
|
||||
while (obj->tick_thread_active) {
|
||||
obj->rot_x += 2;
|
||||
obj->rot_y += 2;
|
||||
obj->LockGL();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, -5);
|
||||
glRotatef(obj->rot_x, 1, 0, 0);
|
||||
glRotatef(obj->rot_y, 0, 1, 0);
|
||||
obj->UnlockGL();
|
||||
if (obj->LockLooperWithTimeout(20000) == B_OK) {
|
||||
obj->Draw(obj->Bounds());
|
||||
obj->UnlockLooper();
|
||||
}
|
||||
snooze(16667);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
thread_id tick_thread;
|
||||
bool tick_thread_active;
|
||||
|
||||
float rot_x, rot_y;
|
||||
uint8 texture[64*64*3];
|
||||
};
|
||||
|
||||
|
||||
// Window class
|
||||
class AboutWindowT : public BWindow {
|
||||
public:
|
||||
AboutWindowT() : BWindow(about_frame, NULL, B_MODAL_WINDOW_LOOK, B_FLOATING_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK)
|
||||
{
|
||||
Lock();
|
||||
MoveTo(100, 100);
|
||||
BRect r = Bounds();
|
||||
r.right = 100;
|
||||
AboutView3D *view_3d = new AboutView3D(r);
|
||||
AddChild(view_3d);
|
||||
r = Bounds();
|
||||
r.left = 100;
|
||||
AboutViewT *view = new AboutViewT(r);
|
||||
AddChild(view);
|
||||
view->SetHighColor(0, 0, 0);
|
||||
view->SetViewColor(fill_color);
|
||||
view->MakeFocus();
|
||||
Unlock();
|
||||
Show();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Open "About" window
|
||||
*/
|
||||
|
||||
void OpenAboutWindow(void)
|
||||
{
|
||||
new AboutWindowT;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../../../BasiliskII/src/BeOS/audio_beos.cpp
|
|
@ -1,374 +0,0 @@
|
|||
/*
|
||||
* clip_beos.cpp - Clipboard handling, BeOS implementation
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <support/UTF8.h>
|
||||
|
||||
#include "clip.h"
|
||||
#include "main.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "emul_op.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Global variables
|
||||
static bool we_put_this_data = false; // Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the Be side
|
||||
static BTranslatorRoster *roster;
|
||||
static float input_cap = 0;
|
||||
static translator_info input_info;
|
||||
static float output_cap = 0;
|
||||
static translator_id output_trans = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Clipboard manager thread (for calling clipboard functions; this is not safe
|
||||
* under R4 when running on the MacOS stack in kernel space)
|
||||
*/
|
||||
|
||||
// Message constants
|
||||
const uint32 MSG_QUIT_CLIP_MANAGER = 'quit';
|
||||
const uint32 MSG_PUT_TEXT = 'ptxt';
|
||||
|
||||
static thread_id cm_thread = -1;
|
||||
static sem_id cm_done_sem = -1;
|
||||
|
||||
// Argument passing
|
||||
static void *cm_scrap;
|
||||
static int32 cm_length;
|
||||
|
||||
static status_t clip_manager(void *arg)
|
||||
{
|
||||
for (;;) {
|
||||
|
||||
// Receive message
|
||||
thread_id sender;
|
||||
uint32 code = receive_data(&sender, NULL, 0);
|
||||
D(bug("Clipboard manager received %08lx\n", code));
|
||||
switch (code) {
|
||||
case MSG_QUIT_CLIP_MANAGER:
|
||||
return 0;
|
||||
|
||||
case MSG_PUT_TEXT:
|
||||
if (be_clipboard->Lock()) {
|
||||
be_clipboard->Clear();
|
||||
BMessage *clipper = be_clipboard->Data();
|
||||
|
||||
// Convert text from Mac charset to UTF-8
|
||||
int32 dest_length = cm_length * 3;
|
||||
int32 state = 0;
|
||||
char *inbuf = new char[cm_length];
|
||||
memcpy(inbuf, cm_scrap, cm_length); // Copy to user space
|
||||
char *outbuf = new char[dest_length];
|
||||
if (convert_to_utf8(B_MAC_ROMAN_CONVERSION, inbuf, &cm_length, outbuf, &dest_length, &state) == B_OK) {
|
||||
for (int i=0; i<dest_length; i++)
|
||||
if (outbuf[i] == 13)
|
||||
outbuf[i] = 10;
|
||||
|
||||
// Add text to Be clipboard
|
||||
clipper->AddData("text/plain", B_MIME_TYPE, outbuf, dest_length);
|
||||
be_clipboard->Commit();
|
||||
} else {
|
||||
D(bug(" text conversion failed\n"));
|
||||
}
|
||||
delete[] outbuf;
|
||||
delete[] inbuf;
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Acknowledge
|
||||
release_sem(cm_done_sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize clipboard
|
||||
*/
|
||||
|
||||
void ClipInit(void)
|
||||
{
|
||||
// check if there is a translator that can handle the pict datatype
|
||||
roster = BTranslatorRoster::Default();
|
||||
int32 num_translators, i,j;
|
||||
translator_id *translators;
|
||||
const char *translator_name, *trans_info;
|
||||
int32 translator_version;
|
||||
const translation_format *t_formats;
|
||||
long t_num;
|
||||
|
||||
roster->GetAllTranslators(&translators, &num_translators);
|
||||
for (i=0;i<num_translators;i++) {
|
||||
roster->GetTranslatorInfo(translators[i], &translator_name,
|
||||
&trans_info, &translator_version);
|
||||
D(bug("found translator %s: %s (%.2f)\n", translator_name, trans_info,
|
||||
translator_version/100.));
|
||||
// does this translator support the pict datatype ?
|
||||
roster->GetInputFormats(translators[i], &t_formats,&t_num);
|
||||
//printf(" supports %d input formats \n",t_num);
|
||||
for (j=0;j<t_num;j++) {
|
||||
if (!strcmp (t_formats[j].MIME,"image/pict")) {
|
||||
// matching translator found
|
||||
if (t_formats[j].capability>input_cap) {
|
||||
input_info.type = t_formats[j].type;
|
||||
input_info.group = t_formats[j].group;
|
||||
input_info.quality = t_formats[j].quality;
|
||||
input_info.capability = t_formats[j].capability;
|
||||
strcpy(input_info.MIME,t_formats[j].MIME);
|
||||
strcpy(input_info.name,t_formats[j].name);
|
||||
input_info.translator=translators[i];
|
||||
input_cap = t_formats[j].capability;
|
||||
}
|
||||
D(bug("matching input translator found:type:%c%c%c%c group:%c%c%c%c quality:%f capability:%f MIME:%s name:%s\n",
|
||||
t_formats[j].type>>24,t_formats[j].type>>16,t_formats[j].type>>8,t_formats[j].type,
|
||||
t_formats[j].group>>24,t_formats[j].group>>16,t_formats[j].group>>8,t_formats[j].group,
|
||||
t_formats[j].quality,
|
||||
t_formats[j].capability,t_formats[j].MIME,
|
||||
t_formats[j].name));
|
||||
}
|
||||
|
||||
}
|
||||
roster->GetOutputFormats(translators[i], &t_formats,&t_num);
|
||||
//printf("and %d output formats \n",t_num);
|
||||
for (j=0;j<t_num;j++) {
|
||||
if (!strcmp (t_formats[j].MIME,"image/pict")) {
|
||||
if (t_formats[j].capability>output_cap) {
|
||||
output_trans = translators[i];
|
||||
output_cap = t_formats[j].capability;
|
||||
}
|
||||
D(bug("matching output translator found:type:%c%c%c%c group:%c%c%c%c quality:%f capability:%f MIME:%s name:%s\n",
|
||||
t_formats[j].type>>24,t_formats[j].type>>16,t_formats[j].type>>8,t_formats[j].type,
|
||||
t_formats[j].group>>24,t_formats[j].group>>16,t_formats[j].group>>8,t_formats[j].group,
|
||||
t_formats[j].quality,
|
||||
t_formats[j].capability,t_formats[j].MIME,
|
||||
t_formats[j].name));
|
||||
}
|
||||
}
|
||||
}
|
||||
delete [] translators; // clean up our droppings
|
||||
|
||||
// Start clipboard manager thread
|
||||
cm_done_sem = create_sem(0, "Clipboard Manager Done");
|
||||
cm_thread = spawn_thread(clip_manager, "Clipboard Manager", B_NORMAL_PRIORITY, NULL);
|
||||
resume_thread(cm_thread);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialize clipboard
|
||||
*/
|
||||
|
||||
void ClipExit(void)
|
||||
{
|
||||
// Stop clipboard manager
|
||||
if (cm_thread > 0) {
|
||||
status_t l;
|
||||
send_data(cm_thread, MSG_QUIT_CLIP_MANAGER, NULL, 0);
|
||||
while (wait_for_thread(cm_thread, &l) == B_INTERRUPTED) ;
|
||||
}
|
||||
|
||||
// Delete semaphores
|
||||
delete_sem(cm_done_sem);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mac application wrote to clipboard
|
||||
*/
|
||||
|
||||
void PutScrap(uint32 type, void *scrap, int32 length)
|
||||
{
|
||||
D(bug("PutScrap type %08lx, data %p, length %ld\n", type, scrap, length));
|
||||
if (we_put_this_data) {
|
||||
we_put_this_data = false;
|
||||
return;
|
||||
}
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case 'TEXT':
|
||||
D(bug(" clipping TEXT\n"));
|
||||
cm_scrap = scrap;
|
||||
cm_length = length;
|
||||
while (send_data(cm_thread, MSG_PUT_TEXT, NULL, 0) == B_INTERRUPTED) ;
|
||||
while (acquire_sem(cm_done_sem) == B_INTERRUPTED) ;
|
||||
break;
|
||||
|
||||
case 'PICT':
|
||||
D(bug(" clipping PICT\n"));
|
||||
//!! this has to be converted to use the Clipboard Manager
|
||||
#if 0
|
||||
if (be_clipboard->Lock()) {
|
||||
be_clipboard->Clear();
|
||||
BMessage *clipper = be_clipboard->Data();
|
||||
// Waaaah! This crashes!
|
||||
if (input_cap > 0) { // if there is an converter for PICT datatype convert data to bitmap.
|
||||
BMemoryIO *in_buffer = new BMemoryIO(scrap, length);
|
||||
BMallocIO *out_buffer = new BMallocIO();
|
||||
status_t result=roster->Translate(in_buffer,&input_info,NULL,out_buffer,B_TRANSLATOR_BITMAP);
|
||||
clipper->AddData("image/x-be-bitmap", B_MIME_TYPE, out_buffer->Buffer(), out_buffer->BufferLength());
|
||||
D(bug("conversion result:%08x buffer_size:%d\n",result,out_buffer->BufferLength()));
|
||||
delete in_buffer;
|
||||
delete out_buffer;
|
||||
}
|
||||
clipper->AddData("image/pict", B_MIME_TYPE, scrap, length);
|
||||
be_clipboard->Commit();
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac application zeroes clipboard
|
||||
*/
|
||||
|
||||
void ZeroScrap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac application reads clipboard
|
||||
*/
|
||||
|
||||
void GetScrap(void **handle, uint32 type, int32 offset)
|
||||
{
|
||||
M68kRegisters r;
|
||||
D(bug("GetScrap handle %p, type %08lx, offset %ld\n", handle, type, offset));
|
||||
return; //!! GetScrap is currently broken (should use Clipboard Manager)
|
||||
//!! replace with clipboard notification in BeOS R4.1
|
||||
|
||||
switch (type) {
|
||||
case 'TEXT':
|
||||
D(bug(" clipping TEXT\n"));
|
||||
if (be_clipboard->Lock()) {
|
||||
BMessage *clipper = be_clipboard->Data();
|
||||
char *clip;
|
||||
ssize_t length;
|
||||
|
||||
// Check if we already copied this data
|
||||
if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE))
|
||||
return;
|
||||
bigtime_t cookie = system_time();
|
||||
clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t));
|
||||
|
||||
// No, is there text in it?
|
||||
if (clipper->FindData("text/plain", B_MIME_TYPE, &clip, &length) == B_OK) {
|
||||
D(bug(" text/plain found\n"));
|
||||
|
||||
// Convert text from UTF-8 to Mac charset
|
||||
int32 src_length = length;
|
||||
int32 dest_length = length;
|
||||
int32 state = 0;
|
||||
char *outbuf = new char[dest_length];
|
||||
if (convert_from_utf8(B_MAC_ROMAN_CONVERSION, clip, &src_length, outbuf, &dest_length, &state) == B_OK) {
|
||||
for (int i=0; i<dest_length; i++)
|
||||
if (outbuf[i] == 10)
|
||||
outbuf[i] = 13;
|
||||
|
||||
// Add text to Mac clipboard
|
||||
static uint16 proc[] = {
|
||||
0x598f, // subq.l #4,sp
|
||||
0xa9fc, // ZeroScrap()
|
||||
0x2f3c, 0, 0, // move.l #length,-(sp)
|
||||
0x2f3c, 'TE', 'XT', // move.l #'TEXT',-(sp)
|
||||
0x2f3c, 0, 0, // move.l #outbuf,-(sp)
|
||||
0xa9fe, // PutScrap()
|
||||
0x588f, // addq.l #4,sp
|
||||
M68K_RTS
|
||||
};
|
||||
*(int32 *)(proc + 3) = dest_length;
|
||||
*(char **)(proc + 9) = outbuf;
|
||||
we_put_this_data = true;
|
||||
Execute68k((uint32)proc, &r);
|
||||
} else {
|
||||
D(bug(" text conversion failed\n"));
|
||||
}
|
||||
delete[] outbuf;
|
||||
}
|
||||
be_clipboard->Commit();
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PICT':
|
||||
D(bug(" clipping PICT\n"));
|
||||
if (be_clipboard->Lock()) {
|
||||
BMessage *clipper = be_clipboard->Data();
|
||||
char *clip;
|
||||
ssize_t length;
|
||||
|
||||
// Check if we already copied this data
|
||||
if (clipper->HasData("application/x-SheepShaver-cookie", B_MIME_TYPE))
|
||||
return;
|
||||
bigtime_t cookie = system_time();
|
||||
clipper->AddData("application/x-SheepShaver-cookie", B_MIME_TYPE, &cookie, sizeof(bigtime_t));
|
||||
|
||||
static uint16 proc2[] = {
|
||||
0x598f, // subq.l #4,sp
|
||||
0xa9fc, // ZeroScrap()
|
||||
0x2f3c, 0, 0, // move.l #length,-(sp)
|
||||
0x2f3c, 'PI', 'CT', // move.l #'PICT',-(sp)
|
||||
0x2f3c, 0, 0, // move.l #buf,-(sp)
|
||||
0xa9fe, // PutScrap()
|
||||
0x588f, // addq.l #4,sp
|
||||
M68K_RTS
|
||||
};
|
||||
|
||||
// No, is there a pict ?
|
||||
if (clipper->FindData("image/pict", B_MIME_TYPE, &clip, &length) == B_OK ) {
|
||||
D(bug(" image/pict found\n"));
|
||||
|
||||
// Add pict to Mac clipboard
|
||||
*(int32 *)(proc2 + 3) = length;
|
||||
*(char **)(proc2 + 9) = clip;
|
||||
we_put_this_data = true;
|
||||
Execute68k((uint32)proc2, &r);
|
||||
#if 0
|
||||
// No, is there a bitmap ?
|
||||
} else if (clipper->FindData("image/x-be-bitmap", B_MIME_TYPE, &clip, &length) == B_OK || output_cap > 0) {
|
||||
D(bug(" image/x-be-bitmap found\nstarting conversion to PICT\n"));
|
||||
|
||||
BMemoryIO *in_buffer = new BMemoryIO(clip, length);
|
||||
BMallocIO *out_buffer = new BMallocIO();
|
||||
status_t result=roster->Translate(output_trans,in_buffer,NULL,out_buffer,'PICT');
|
||||
D(bug("result of conversion:%08x buffer_size:%d\n",result,out_buffer->BufferLength()));
|
||||
|
||||
// Add pict to Mac clipboard
|
||||
*(int32 *)(proc2 + 3) = out_buffer->BufferLength();
|
||||
*(char **)(proc2 + 9) = (char *)out_buffer->Buffer();
|
||||
we_put_this_data = true;
|
||||
Execute68k(proc2, &r);
|
||||
|
||||
delete in_buffer;
|
||||
delete out_buffer;
|
||||
#endif
|
||||
}
|
||||
be_clipboard->Commit();
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,400 +0,0 @@
|
|||
/*
|
||||
* ether_beos.cpp - SheepShaver Ethernet Device Driver (DLPI), BeOS specific stuff
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Marc Hellwig and Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "ether.h"
|
||||
#include "ether_defs.h"
|
||||
#include "prefs.h"
|
||||
#include "xlowmem.h"
|
||||
#include "main.h"
|
||||
#include "user_strings.h"
|
||||
#include "sheep_net.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#define STATISTICS 0
|
||||
#define MONITOR 0
|
||||
|
||||
|
||||
// Global variables
|
||||
static thread_id read_thread; // Packet receiver thread
|
||||
static bool ether_thread_active = true; // Flag for quitting the receiver thread
|
||||
|
||||
static area_id buffer_area; // Packet buffer area
|
||||
static net_buffer *net_buffer_ptr; // Pointer to packet buffer
|
||||
static sem_id read_sem, write_sem; // Semaphores to trigger packet reading/writing
|
||||
static uint32 rd_pos; // Current read position in packet buffer
|
||||
static uint32 wr_pos; // Current write position in packet buffer
|
||||
|
||||
static bool net_open = false; // Flag: initialization succeeded, network device open
|
||||
|
||||
|
||||
// Prototypes
|
||||
static status_t AO_receive_thread(void *data);
|
||||
|
||||
|
||||
/*
|
||||
* Initialize ethernet
|
||||
*/
|
||||
|
||||
void EtherInit(void)
|
||||
{
|
||||
// Do nothing if the user disabled the network
|
||||
if (PrefsFindBool("nonet"))
|
||||
return;
|
||||
|
||||
// find net-server team
|
||||
i_wanna_try_that_again:
|
||||
bool found_add_on = false;
|
||||
team_info t_info;
|
||||
int32 t_cookie = 0;
|
||||
image_info i_info;
|
||||
int32 i_cookie = 0;
|
||||
while (get_next_team_info(&t_cookie, &t_info) == B_NO_ERROR) {
|
||||
if (strstr(t_info.args,"net_server")!=NULL) {
|
||||
// check if sheep_net add-on is loaded
|
||||
while (get_next_image_info(t_info.team,&i_cookie,&i_info) == B_NO_ERROR) {
|
||||
if (strstr(i_info.name,"sheep_net")!=NULL) {
|
||||
found_add_on = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_add_on) break;
|
||||
}
|
||||
if (!found_add_on) {
|
||||
|
||||
// Search for sheep_net in network config file
|
||||
char str[1024];
|
||||
bool sheep_net_found = false;
|
||||
FILE *fin = fopen("/boot/home/config/settings/network", "r");
|
||||
while (!feof(fin)) {
|
||||
fgets(str, 1024, fin);
|
||||
if (strstr(str, "PROTOCOLS"))
|
||||
if (strstr(str, "sheep_net"))
|
||||
sheep_net_found = true;
|
||||
}
|
||||
fclose(fin);
|
||||
|
||||
// It was found, so something else must be wrong
|
||||
if (sheep_net_found) {
|
||||
WarningAlert(GetString(STR_NO_NET_ADDON_WARN));
|
||||
return;
|
||||
}
|
||||
|
||||
// Not found, inform the user
|
||||
if (!ChoiceAlert(GetString(STR_NET_CONFIG_MODIFY_WARN), GetString(STR_OK_BUTTON), GetString(STR_CANCEL_BUTTON)))
|
||||
return;
|
||||
|
||||
// Change the network config file and restart the network
|
||||
fin = fopen("/boot/home/config/settings/network", "r");
|
||||
FILE *fout = fopen("/boot/home/config/settings/network.2", "w");
|
||||
bool global_found = false;
|
||||
bool modified = false;
|
||||
while (!feof(fin)) {
|
||||
str[0] = 0;
|
||||
fgets(str, 1024, fin);
|
||||
if (!global_found && strstr(str, "GLOBAL:")) {
|
||||
global_found = true;
|
||||
} else if (global_found && !modified && strstr(str, "PROTOCOLS")) {
|
||||
str[strlen(str)-1] = 0;
|
||||
strcat(str, " sheep_net\n");
|
||||
modified = true;
|
||||
} else if (global_found && !modified && strlen(str) > 2 && str[strlen(str) - 2] == ':') {
|
||||
fputs("\tPROTOCOLS = sheep_net\n", fout);
|
||||
modified = true;
|
||||
}
|
||||
fputs(str, fout);
|
||||
}
|
||||
if (!modified)
|
||||
fputs("\tPROTOCOLS = sheep_net\n", fout);
|
||||
fclose(fout);
|
||||
fclose(fin);
|
||||
remove("/boot/home/config/settings/network.orig");
|
||||
rename("/boot/home/config/settings/network", "/boot/home/config/settings/network.orig");
|
||||
rename("/boot/home/config/settings/network.2", "/boot/home/config/settings/network");
|
||||
|
||||
app_info ai;
|
||||
if (be_roster->GetAppInfo("application/x-vnd.Be-NETS", &ai) == B_OK) {
|
||||
BMessenger msg(NULL, ai.team);
|
||||
if (msg.IsValid()) {
|
||||
while (be_roster->IsRunning("application/x-vnd.Be-NETS")) {
|
||||
msg.SendMessage(B_QUIT_REQUESTED);
|
||||
snooze(500000);
|
||||
}
|
||||
}
|
||||
}
|
||||
BPath path;
|
||||
find_directory(B_BEOS_BOOT_DIRECTORY, &path);
|
||||
path.Append("Netscript");
|
||||
char *argv[3] = {"/bin/sh", (char *)path.Path(), NULL};
|
||||
thread_id net_server = load_image(2, argv, environ);
|
||||
resume_thread(net_server);
|
||||
status_t l;
|
||||
wait_for_thread(net_server, &l);
|
||||
goto i_wanna_try_that_again;
|
||||
}
|
||||
|
||||
// Set up communications with add-on
|
||||
area_id handler_buffer;
|
||||
if ((handler_buffer = find_area("packet buffer")) < B_NO_ERROR) {
|
||||
WarningAlert(GetString(STR_NET_ADDON_INIT_FAILED));
|
||||
return;
|
||||
}
|
||||
if ((buffer_area = clone_area("local packet buffer", &net_buffer_ptr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, handler_buffer)) < B_NO_ERROR) {
|
||||
D(bug("EtherInit: couldn't clone packet area\n"));
|
||||
WarningAlert(GetString(STR_NET_ADDON_CLONE_FAILED));
|
||||
return;
|
||||
}
|
||||
if ((read_sem = create_sem(0, "ether read")) < B_NO_ERROR) {
|
||||
printf("FATAL: can't create Ethernet semaphore\n");
|
||||
return;
|
||||
}
|
||||
net_buffer_ptr->read_sem = read_sem;
|
||||
write_sem = net_buffer_ptr->write_sem;
|
||||
read_thread = spawn_thread(AO_receive_thread, "ether read", B_URGENT_DISPLAY_PRIORITY, NULL);
|
||||
resume_thread(read_thread);
|
||||
for (int i=0; i<WRITE_PACKET_COUNT; i++)
|
||||
net_buffer_ptr->write[i].cmd = IN_USE | (ACTIVATE_SHEEP_NET << 8);
|
||||
rd_pos = wr_pos = 0;
|
||||
release_sem(write_sem);
|
||||
|
||||
// Everything OK
|
||||
net_open = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Exit ethernet
|
||||
*/
|
||||
|
||||
void EtherExit(void)
|
||||
{
|
||||
if (net_open) {
|
||||
|
||||
// Close communications with add-on
|
||||
for (int i=0; i<WRITE_PACKET_COUNT; i++)
|
||||
net_buffer_ptr->write[i].cmd = IN_USE | (DEACTIVATE_SHEEP_NET << 8);
|
||||
release_sem(write_sem);
|
||||
|
||||
// Quit receiver thread
|
||||
ether_thread_active = false;
|
||||
status_t result;
|
||||
release_sem(read_sem);
|
||||
while (wait_for_thread(read_thread, &result) == B_INTERRUPTED) ;
|
||||
|
||||
delete_sem(read_sem);
|
||||
delete_area(buffer_area);
|
||||
}
|
||||
|
||||
#if STATISTICS
|
||||
// Show statistics
|
||||
printf("%ld messages put on write queue\n", num_wput);
|
||||
printf("%ld error acks\n", num_error_acks);
|
||||
printf("%ld packets transmitted (%ld raw, %ld normal)\n", num_tx_packets, num_tx_raw_packets, num_tx_normal_packets);
|
||||
printf("%ld tx packets dropped because buffer full\n", num_tx_buffer_full);
|
||||
printf("%ld packets received\n", num_rx_packets);
|
||||
printf("%ld packets passed upstream (%ld Fast Path, %ld normal)\n", num_rx_fastpath + num_unitdata_ind, num_rx_fastpath, num_unitdata_ind);
|
||||
printf("EtherIRQ called %ld times\n", num_ether_irq);
|
||||
printf("%ld rx packets dropped due to low memory\n", num_rx_no_mem);
|
||||
printf("%ld rx packets dropped because no stream found\n", num_rx_dropped);
|
||||
printf("%ld rx packets dropped because stream not ready\n", num_rx_stream_not_ready);
|
||||
printf("%ld rx packets dropped because no memory for unitdata_ind\n", num_rx_no_unitdata_mem);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ask add-on for ethernet hardware address
|
||||
*/
|
||||
|
||||
void AO_get_ethernet_address(uint32 arg)
|
||||
{
|
||||
uint8 *addr = Mac2HostAddr(arg);
|
||||
if (net_open) {
|
||||
OTCopy48BitAddress(net_buffer_ptr->ether_addr, addr);
|
||||
} else {
|
||||
addr[0] = 0x12;
|
||||
addr[1] = 0x34;
|
||||
addr[2] = 0x56;
|
||||
addr[3] = 0x78;
|
||||
addr[4] = 0x9a;
|
||||
addr[5] = 0xbc;
|
||||
}
|
||||
D(bug("AO_get_ethernet_address: got address %02x%02x%02x%02x%02x%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tell add-on to enable multicast address
|
||||
*/
|
||||
|
||||
void AO_enable_multicast(uint32 addr)
|
||||
{
|
||||
D(bug("AO_enable_multicast\n"));
|
||||
if (net_open) {
|
||||
net_packet *p = &net_buffer_ptr->write[wr_pos];
|
||||
if (p->cmd & IN_USE) {
|
||||
D(bug("WARNING: couldn't enable multicast address\n"));
|
||||
} else {
|
||||
Mac2host_memcpy(p->data, addr, 6);
|
||||
p->length = 6;
|
||||
p->cmd = IN_USE | (ADD_MULTICAST << 8);
|
||||
wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
|
||||
release_sem(write_sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tell add-on to disable multicast address
|
||||
*/
|
||||
|
||||
void AO_disable_multicast(uint32 addr)
|
||||
{
|
||||
D(bug("AO_disable_multicast\n"));
|
||||
if (net_open) {
|
||||
net_packet *p = &net_buffer_ptr->write[wr_pos];
|
||||
if (p->cmd & IN_USE) {
|
||||
D(bug("WARNING: couldn't enable multicast address\n"));
|
||||
} else {
|
||||
Mac2host_memcpy(p->data, addr, 6);
|
||||
p->length = 6;
|
||||
p->cmd = IN_USE | (REMOVE_MULTICAST << 8);
|
||||
wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
|
||||
release_sem(write_sem);
|
||||
}
|
||||
D(bug("WARNING: couldn't disable multicast address\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tell add-on to transmit one packet
|
||||
*/
|
||||
|
||||
void AO_transmit_packet(uint32 mp_arg)
|
||||
{
|
||||
D(bug("AO_transmit_packet\n"));
|
||||
if (net_open) {
|
||||
net_packet *p = &net_buffer_ptr->write[wr_pos];
|
||||
if (p->cmd & IN_USE) {
|
||||
D(bug("WARNING: couldn't transmit packet (buffer full)\n"));
|
||||
num_tx_buffer_full++;
|
||||
} else {
|
||||
D(bug(" write packet pos %d\n", i));
|
||||
num_tx_packets++;
|
||||
|
||||
// Copy packet to buffer
|
||||
uint8 *start;
|
||||
uint8 *bp = start = p->data;
|
||||
mblk_t *mp = Mac2HostAddr(mp_arg);
|
||||
while (mp) {
|
||||
uint32 size = mp->b_wptr - mp->b_rptr;
|
||||
memcpy(bp, mp->b_rptr, size);
|
||||
bp += size;
|
||||
mp = mp->b_cont;
|
||||
}
|
||||
|
||||
#if MONITOR
|
||||
bug("Sending Ethernet packet:\n");
|
||||
for (int i=0; i<(uint32)(bp - start); i++) {
|
||||
bug("%02lx ", start[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
|
||||
// Notify add-on
|
||||
p->length = (uint32)(bp - start);
|
||||
p->cmd = IN_USE | (SHEEP_PACKET << 8);
|
||||
wr_pos = (wr_pos + 1) % WRITE_PACKET_COUNT;
|
||||
release_sem(write_sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Packet reception thread
|
||||
*/
|
||||
|
||||
static status_t AO_receive_thread(void *data)
|
||||
{
|
||||
while (ether_thread_active) {
|
||||
if (net_buffer_ptr->read[rd_pos].cmd & IN_USE) {
|
||||
if (ether_driver_opened) {
|
||||
D(bug(" packet received, triggering Ethernet interrupt\n"));
|
||||
SetInterruptFlag(INTFLAG_ETHER);
|
||||
TriggerInterrupt();
|
||||
}
|
||||
}
|
||||
acquire_sem_etc(read_sem, 1, B_TIMEOUT, 25000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ethernet interrupt
|
||||
*/
|
||||
|
||||
void EtherIRQ(void)
|
||||
{
|
||||
D(bug("EtherIRQ\n"));
|
||||
num_ether_irq++;
|
||||
OTEnterInterrupt();
|
||||
|
||||
// Send received packets to OpenTransport
|
||||
net_packet *p = &net_buffer_ptr->read[rd_pos];
|
||||
while (p->cmd & IN_USE) {
|
||||
if ((p->cmd >> 8) == SHEEP_PACKET) {
|
||||
num_rx_packets++;
|
||||
D(bug(" read packet pos %d\n", i));
|
||||
uint32 size = p->length;
|
||||
|
||||
#if MONITOR
|
||||
bug("Receiving Ethernet packet:\n");
|
||||
for (int i=0; i<size; i++) {
|
||||
bug("%02lx ", p->data[i]);
|
||||
}
|
||||
bug("\n");
|
||||
#endif
|
||||
|
||||
// Wrap packet in message block
|
||||
//!! maybe use esballoc()
|
||||
mblk_t *mp;
|
||||
if ((mp = allocb(size, 0)) != NULL) {
|
||||
D(bug(" packet data at %p\n", (void *)mp->b_rptr));
|
||||
memcpy(mp->b_rptr, p->data, size);
|
||||
mp->b_wptr += size;
|
||||
ether_packet_received(mp);
|
||||
} else {
|
||||
D(bug("WARNING: Cannot allocate mblk for received packet\n"));
|
||||
num_rx_no_mem++;
|
||||
}
|
||||
}
|
||||
p->cmd = 0; // Free packet
|
||||
rd_pos = (rd_pos + 1) % READ_PACKET_COUNT;
|
||||
p = &net_buffer_ptr->read[rd_pos];
|
||||
}
|
||||
OTLeaveInterrupt();
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../../../BasiliskII/src/BeOS/extfs_beos.cpp
|
File diff suppressed because it is too large
Load Diff
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* prefs_beos.cpp - Preferences handling, BeOS specific things
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <StorageKit.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "prefs.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
// Platform-specific preferences items
|
||||
prefs_desc platform_prefs_items[] = {
|
||||
{"bitbang", TYPE_BOOLEAN, false, "draw Mac desktop directly on screen in window mode"},
|
||||
{"idlewait", TYPE_BOOLEAN, false, "sleep when idle"},
|
||||
{NULL, TYPE_END, false, NULL} // End of list
|
||||
};
|
||||
|
||||
|
||||
// Preferences file name and path
|
||||
const char PREFS_FILE_NAME[] = "SheepShaver_prefs";
|
||||
static BPath prefs_path;
|
||||
|
||||
// Modification date of prefs file
|
||||
time_t PrefsFileDate = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Load preferences from settings file
|
||||
*/
|
||||
|
||||
void LoadPrefs(const char *vmdir)
|
||||
{
|
||||
// Construct prefs path
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY, &prefs_path, true);
|
||||
prefs_path.Append(PREFS_FILE_NAME);
|
||||
|
||||
// Read preferences from settings file
|
||||
FILE *f = fopen(prefs_path.Path(), "r");
|
||||
if (f == NULL) // Not found in settings directory, look in app directory
|
||||
f = fopen(PREFS_FILE_NAME, "r");
|
||||
if (f != NULL) {
|
||||
LoadPrefsFromStream(f);
|
||||
|
||||
struct stat s;
|
||||
fstat(fileno(f), &s);
|
||||
PrefsFileDate = s.st_ctime;
|
||||
fclose(f);
|
||||
|
||||
} else {
|
||||
|
||||
// No prefs file, save defaults
|
||||
SavePrefs();
|
||||
PrefsFileDate = real_time_clock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save preferences to settings file
|
||||
*/
|
||||
|
||||
void SavePrefs(void)
|
||||
{
|
||||
FILE *f;
|
||||
if ((f = fopen(prefs_path.Path(), "w")) != NULL) {
|
||||
SavePrefsToStream(f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add defaults of platform-specific prefs items
|
||||
* You may also override the defaults set in PrefsInit()
|
||||
*/
|
||||
|
||||
void AddPlatformPrefsDefaults(void)
|
||||
{
|
||||
PrefsReplaceString("extfs", "/boot");
|
||||
PrefsAddInt32("windowmodes",
|
||||
B_8_BIT_640x480 | B_15_BIT_640x480 | B_32_BIT_640x480 |
|
||||
B_8_BIT_800x600 | B_15_BIT_800x600 | B_32_BIT_800x600
|
||||
);
|
||||
PrefsAddInt32("screenmodes",
|
||||
B_8_BIT_640x480 | B_15_BIT_640x480 | B_32_BIT_640x480 |
|
||||
B_8_BIT_800x600 | B_15_BIT_800x600 | B_32_BIT_800x600 |
|
||||
B_8_BIT_1024x768 | B_15_BIT_1024x768
|
||||
);
|
||||
PrefsAddBool("bitbang", false);
|
||||
PrefsAddBool("idlewait", true);
|
||||
}
|
|
@ -1,877 +0,0 @@
|
|||
/*
|
||||
* prefs_editor_beos.cpp - Preferences editor, BeOS implementation
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <SerialPort.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fs_info.h>
|
||||
|
||||
#include "prefs_editor.h"
|
||||
#include "prefs.h"
|
||||
#include "main.h"
|
||||
#include "cdrom.h"
|
||||
#include "xpram.h"
|
||||
#include "about_window.h"
|
||||
#include "user_strings.h"
|
||||
|
||||
|
||||
// Special colors
|
||||
const rgb_color fill_color = {216, 216, 216, 0};
|
||||
const rgb_color slider_fill_color = {102, 152, 255, 0};
|
||||
|
||||
|
||||
// Window messages
|
||||
const uint32 MSG_OK = 'okok'; // "Start" clicked
|
||||
const uint32 MSG_CANCEL = 'cncl'; // "Quit" clicked
|
||||
const uint32 MSG_ZAP_PRAM = 'zprm';
|
||||
|
||||
const int NUM_PANES = 4;
|
||||
|
||||
const uint32 MSG_VOLUME_SELECTED = 'volu'; // "Volumes" pane
|
||||
const uint32 MSG_VOLUME_INVOKED = 'voli';
|
||||
const uint32 MSG_ADD_VOLUME = 'addv';
|
||||
const uint32 MSG_CREATE_VOLUME = 'crev';
|
||||
const uint32 MSG_REMOVE_VOLUME = 'remv';
|
||||
const uint32 MSG_ADD_VOLUME_PANEL = 'advp';
|
||||
const uint32 MSG_CREATE_VOLUME_PANEL = 'crvp';
|
||||
const uint32 MSG_DEVICE_NAME = 'devn';
|
||||
const uint32 MSG_BOOT_ANY = 'bany';
|
||||
const uint32 MSG_BOOT_CDROM = 'bcdr';
|
||||
const uint32 MSG_NOCDROM = 'nocd';
|
||||
|
||||
const uint32 MSG_REF_5HZ = ' 5Hz'; // "Graphics" pane
|
||||
const uint32 MSG_REF_7_5HZ = ' 7Hz';
|
||||
const uint32 MSG_REF_10HZ = '10Hz';
|
||||
const uint32 MSG_REF_15HZ = '15Hz';
|
||||
const uint32 MSG_REF_30HZ = '30Hz';
|
||||
const uint32 MSG_GFXACCEL = 'gfac';
|
||||
const uint32 MSG_WINDOW_MODE = 'wmod';
|
||||
const uint32 MSG_SCREEN_MODE = 'smod';
|
||||
const uint32 MSG_NOSOUND = 'nosn';
|
||||
|
||||
const uint32 MSG_SER_A = 'sera'; // "Serial"/"Network" pane
|
||||
const uint32 MSG_SER_B = 'serb';
|
||||
const uint32 MSG_NONET = 'noet';
|
||||
|
||||
const uint32 MSG_RAMSIZE = 'rmsz'; // "Memory" pane
|
||||
const uint32 MSG_IGNORESEGV = 'isgv';
|
||||
const uint32 MSG_IDLEWAIT = 'idlw';
|
||||
|
||||
|
||||
// RAM size slider class
|
||||
class RAMSlider : public BSlider {
|
||||
public:
|
||||
RAMSlider(BRect frame, const char *name, const char *label, BMessage *message,
|
||||
int32 minValue, int32 maxValue, thumb_style thumbType = B_BLOCK_THUMB,
|
||||
uint32 resizingMode = B_FOLLOW_LEFT |
|
||||
B_FOLLOW_TOP,
|
||||
uint32 flags = B_NAVIGABLE | B_WILL_DRAW |
|
||||
B_FRAME_EVENTS) : BSlider(frame, name, label, message, minValue, maxValue, thumbType, resizingMode, flags)
|
||||
{
|
||||
update_text = (char *)malloc(256);
|
||||
}
|
||||
|
||||
virtual ~RAMSlider()
|
||||
{
|
||||
if (update_text)
|
||||
free(update_text);
|
||||
}
|
||||
|
||||
virtual char *UpdateText(void) const
|
||||
{
|
||||
if (update_text) {
|
||||
sprintf(update_text, GetString(STR_RAMSIZE_FMT), Value());
|
||||
}
|
||||
return update_text;
|
||||
}
|
||||
|
||||
private:
|
||||
char *update_text;
|
||||
};
|
||||
|
||||
|
||||
// Volumes list view class
|
||||
class VolumeListView : public BListView {
|
||||
public:
|
||||
VolumeListView(BRect frame, const char *name, list_view_type type = B_SINGLE_SELECTION_LIST, uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP, uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE)
|
||||
: BListView(frame, name, type, resizeMask, flags)
|
||||
{}
|
||||
|
||||
// Handle dropped files and volumes
|
||||
virtual void MessageReceived(BMessage *msg)
|
||||
{
|
||||
if (msg->what == B_SIMPLE_DATA) {
|
||||
BMessage msg2(MSG_ADD_VOLUME_PANEL);
|
||||
entry_ref ref;
|
||||
for (int i=0; msg->FindRef("refs", i, &ref) == B_NO_ERROR; i++)
|
||||
msg2.AddRef("refs", &ref);
|
||||
Window()->PostMessage(&msg2);
|
||||
} else
|
||||
BListView::MessageReceived(msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Number-entry BTextControl
|
||||
class NumberControl : public BTextControl {
|
||||
public:
|
||||
NumberControl(BRect frame, float divider, const char *name, const char *label, long value, BMessage *message)
|
||||
: BTextControl(frame, name, label, NULL, message, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE)
|
||||
{
|
||||
SetDivider(divider);
|
||||
for (int c=0; c<256; c++)
|
||||
if (!isdigit(c) && c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW)
|
||||
((BTextView *)ChildAt(0))->DisallowChar(c);
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
// Set integer value
|
||||
void SetValue(long value)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "%ld", value);
|
||||
SetText(str);
|
||||
}
|
||||
|
||||
// Get integer value
|
||||
long Value(void)
|
||||
{
|
||||
return atol(Text());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Path-entry BTextControl
|
||||
class PathControl : public BTextControl {
|
||||
public:
|
||||
PathControl(bool dir_ctrl_, BRect frame, const char *name, const char *label, const char *text, BMessage *message) : BTextControl(frame, name, label, text, message), dir_ctrl(dir_ctrl_)
|
||||
{
|
||||
for (int c=0; c<' '; c++)
|
||||
if (c != B_BACKSPACE && c != B_LEFT_ARROW && c != B_RIGHT_ARROW)
|
||||
((BTextView *)ChildAt(0))->DisallowChar(c);
|
||||
}
|
||||
|
||||
virtual void MessageReceived(BMessage *msg)
|
||||
{
|
||||
if (msg->what == B_SIMPLE_DATA) {
|
||||
entry_ref the_ref;
|
||||
BEntry the_entry;
|
||||
|
||||
// Look for dropped refs
|
||||
if (msg->FindRef("refs", &the_ref) == B_NO_ERROR) {
|
||||
if (the_entry.SetTo(&the_ref) == B_NO_ERROR && (dir_ctrl&& the_entry.IsDirectory() || !dir_ctrl && the_entry.IsFile())) {
|
||||
BPath the_path;
|
||||
the_entry.GetPath(&the_path);
|
||||
SetText(the_path.Path());
|
||||
}
|
||||
} else
|
||||
BTextControl::MessageReceived(msg);
|
||||
|
||||
MakeFocus();
|
||||
} else
|
||||
BTextControl::MessageReceived(msg);
|
||||
}
|
||||
|
||||
private:
|
||||
bool dir_ctrl;
|
||||
};
|
||||
|
||||
|
||||
// Preferences window class
|
||||
class PrefsWindow : public BWindow {
|
||||
public:
|
||||
PrefsWindow(uint32 msg);
|
||||
virtual ~PrefsWindow();
|
||||
virtual void MessageReceived(BMessage *msg);
|
||||
|
||||
private:
|
||||
BView *create_volumes_pane(void);
|
||||
BView *create_graphics_pane(void);
|
||||
BView *create_serial_pane(void);
|
||||
BView *create_memory_pane(void);
|
||||
|
||||
uint32 ok_message;
|
||||
bool send_quit_on_close;
|
||||
|
||||
BMessenger this_messenger;
|
||||
BView *top;
|
||||
BRect top_frame;
|
||||
BTabView *pane_tabs;
|
||||
BView *panes[NUM_PANES];
|
||||
int current_pane;
|
||||
|
||||
VolumeListView *volume_list;
|
||||
BCheckBox *nocdrom_checkbox;
|
||||
BCheckBox *gfxaccel_checkbox;
|
||||
BCheckBox *nosound_checkbox;
|
||||
BCheckBox *nonet_checkbox;
|
||||
BCheckBox *ignoresegv_checkbox;
|
||||
BCheckBox *idlewait_checkbox;
|
||||
RAMSlider *ramsize_slider;
|
||||
PathControl *extfs_control;
|
||||
PathControl *rom_control;
|
||||
|
||||
BFilePanel *add_volume_panel;
|
||||
BFilePanel *create_volume_panel;
|
||||
|
||||
uint32 max_ramsize; // In MB
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Show preferences editor
|
||||
* When the user clicks on "OK", the message given as parameter is sent
|
||||
* to the application; if he clicks on "Quit", B_QUIT_REQUESTED is sent
|
||||
*/
|
||||
|
||||
void PrefsEditor(uint32 msg)
|
||||
{
|
||||
new PrefsWindow(msg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Preferences window constructor
|
||||
*/
|
||||
|
||||
PrefsWindow::PrefsWindow(uint32 msg) : BWindow(BRect(0, 0, 400, 289), GetString(STR_PREFS_TITLE), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS), this_messenger(this)
|
||||
{
|
||||
int i;
|
||||
ok_message = msg;
|
||||
send_quit_on_close = true;
|
||||
|
||||
// Move window to right position
|
||||
Lock();
|
||||
MoveTo(80, 80);
|
||||
|
||||
// Set up menus
|
||||
BMenuBar *bar = new BMenuBar(Bounds(), "menu");
|
||||
BMenu *menu = new BMenu(GetString(STR_PREFS_MENU));
|
||||
menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ABOUT), new BMessage(B_ABOUT_REQUESTED)));
|
||||
menu->AddItem(new BSeparatorItem);
|
||||
menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_START), new BMessage(MSG_OK)));
|
||||
menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_ZAP_PRAM), new BMessage(MSG_ZAP_PRAM)));
|
||||
menu->AddItem(new BSeparatorItem);
|
||||
menu->AddItem(new BMenuItem(GetString(STR_PREFS_ITEM_QUIT), new BMessage(MSG_CANCEL), 'Q'));
|
||||
bar->AddItem(menu);
|
||||
AddChild(bar);
|
||||
SetKeyMenuBar(bar);
|
||||
int mbar_height = bar->Bounds().bottom + 1;
|
||||
|
||||
// Resize window to fit menu bar
|
||||
ResizeBy(0, mbar_height);
|
||||
|
||||
// Light gray background
|
||||
BRect b = Bounds();
|
||||
top = new BView(BRect(0, mbar_height, b.right, b.bottom), "top", B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
AddChild(top);
|
||||
top->SetViewColor(fill_color);
|
||||
top_frame = top->Bounds();
|
||||
|
||||
// Create panes
|
||||
panes[0] = create_volumes_pane();
|
||||
panes[1] = create_graphics_pane();
|
||||
panes[2] = create_serial_pane();
|
||||
panes[3] = create_memory_pane();
|
||||
|
||||
// Prefs item tab view
|
||||
pane_tabs = new BTabView(BRect(10, 10, top_frame.right-10, top_frame.bottom-50), "items", B_WIDTH_FROM_LABEL);
|
||||
for (i=0; i<NUM_PANES; i++)
|
||||
pane_tabs->AddTab(panes[i]);
|
||||
top->AddChild(pane_tabs);
|
||||
|
||||
volume_list->Select(0);
|
||||
|
||||
// Create volume file panels
|
||||
add_volume_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_ADD_VOLUME_PANEL));
|
||||
add_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_ADD_VOLUME_PANEL_BUTTON));
|
||||
add_volume_panel->Window()->SetTitle(GetString(STR_ADD_VOLUME_TITLE));
|
||||
create_volume_panel = new BFilePanel(B_SAVE_PANEL, &this_messenger, NULL, B_FILE_NODE | B_DIRECTORY_NODE, false, new BMessage(MSG_CREATE_VOLUME_PANEL));
|
||||
create_volume_panel->SetButtonLabel(B_DEFAULT_BUTTON, GetString(STR_CREATE_VOLUME_PANEL_BUTTON));
|
||||
create_volume_panel->Window()->SetTitle(GetString(STR_CREATE_VOLUME_TITLE));
|
||||
|
||||
create_volume_panel->Window()->Lock();
|
||||
BView *background = create_volume_panel->Window()->ChildAt(0);
|
||||
background->FindView("PoseView")->ResizeBy(0, -30);
|
||||
background->FindView("VScrollBar")->ResizeBy(0, -30);
|
||||
background->FindView("CountVw")->MoveBy(0, -30);
|
||||
BView *v = background->FindView("HScrollBar");
|
||||
if (v)
|
||||
v->MoveBy(0, -30);
|
||||
else {
|
||||
i = 0;
|
||||
while ((v = background->ChildAt(i++)) != NULL) {
|
||||
if (v->Name() == NULL || v->Name()[0] == 0) {
|
||||
v->MoveBy(0, -30); // unnamed horizontal scroll bar
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
BView *filename = background->FindView("text view");
|
||||
BRect fnr(filename->Frame());
|
||||
fnr.OffsetBy(0, -30);
|
||||
NumberControl *nc = new NumberControl(fnr, 80, "hardfile_size", GetString(STR_HARDFILE_SIZE_CTRL), 40, NULL);
|
||||
background->AddChild(nc);
|
||||
create_volume_panel->Window()->Unlock();
|
||||
|
||||
// "Start" button
|
||||
BButton *button = new BButton(BRect(20, top_frame.bottom-35, 90, top_frame.bottom-10), "start", GetString(STR_START_BUTTON), new BMessage(MSG_OK));
|
||||
top->AddChild(button);
|
||||
SetDefaultButton(button);
|
||||
|
||||
// "Quit" button
|
||||
top->AddChild(new BButton(BRect(top_frame.right-90, top_frame.bottom-35, top_frame.right-20, top_frame.bottom-10), "cancel", GetString(STR_QUIT_BUTTON), new BMessage(MSG_CANCEL)));
|
||||
|
||||
Unlock();
|
||||
Show();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Preferences window destructor
|
||||
*/
|
||||
|
||||
PrefsWindow::~PrefsWindow()
|
||||
{
|
||||
delete add_volume_panel;
|
||||
if (send_quit_on_close)
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create "Volumes" pane
|
||||
*/
|
||||
|
||||
BView *PrefsWindow::create_volumes_pane(void)
|
||||
{
|
||||
BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_VOLUMES_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
pane->SetViewColor(fill_color);
|
||||
float right = pane->Bounds().right-10;
|
||||
|
||||
const char *str;
|
||||
int32 index = 0;
|
||||
volume_list = new VolumeListView(BRect(15, 10, pane->Bounds().right-30, 108), "volumes");
|
||||
while ((str = PrefsFindString("disk", index++)) != NULL)
|
||||
volume_list->AddItem(new BStringItem(str));
|
||||
volume_list->SetSelectionMessage(new BMessage(MSG_VOLUME_SELECTED));
|
||||
volume_list->SetInvocationMessage(new BMessage(MSG_VOLUME_INVOKED));
|
||||
pane->AddChild(new BScrollView("volumes_border", volume_list, B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
|
||||
|
||||
pane->AddChild(new BButton(BRect(10, 113, pane->Bounds().right/3, 133), "add_volume", GetString(STR_ADD_VOLUME_BUTTON), new BMessage(MSG_ADD_VOLUME)));
|
||||
pane->AddChild(new BButton(BRect(pane->Bounds().right/3, 113, pane->Bounds().right*2/3, 133), "create_volume", GetString(STR_CREATE_VOLUME_BUTTON), new BMessage(MSG_CREATE_VOLUME)));
|
||||
pane->AddChild(new BButton(BRect(pane->Bounds().right*2/3, 113, pane->Bounds().right-11, 133), "remove_volume", GetString(STR_REMOVE_VOLUME_BUTTON), new BMessage(MSG_REMOVE_VOLUME)));
|
||||
|
||||
extfs_control = new PathControl(true, BRect(10, 145, right, 160), "extfs", GetString(STR_EXTFS_CTRL), PrefsFindString("extfs"), NULL);
|
||||
extfs_control->SetDivider(90);
|
||||
pane->AddChild(extfs_control);
|
||||
|
||||
BMenuField *menu_field;
|
||||
BPopUpMenu *menu = new BPopUpMenu("");
|
||||
menu_field = new BMenuField(BRect(10, 165, right, 180), "bootdriver", GetString(STR_BOOTDRIVER_CTRL), menu);
|
||||
menu_field->SetDivider(90);
|
||||
menu->AddItem(new BMenuItem(GetString(STR_BOOT_ANY_LAB), new BMessage(MSG_BOOT_ANY)));
|
||||
menu->AddItem(new BMenuItem(GetString(STR_BOOT_CDROM_LAB), new BMessage(MSG_BOOT_CDROM)));
|
||||
pane->AddChild(menu_field);
|
||||
int16 i16 = PrefsFindInt32("bootdriver");
|
||||
BMenuItem *item;
|
||||
if (i16 == 0) {
|
||||
if ((item = menu->FindItem(GetString(STR_BOOT_ANY_LAB))) != NULL)
|
||||
item->SetMarked(true);
|
||||
} else if (i16 == CDROMRefNum) {
|
||||
if ((item = menu->FindItem(GetString(STR_BOOT_CDROM_LAB))) != NULL)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
|
||||
nocdrom_checkbox = new BCheckBox(BRect(10, 185, right, 200), "nocdrom", GetString(STR_NOCDROM_CTRL), new BMessage(MSG_NOCDROM));
|
||||
pane->AddChild(nocdrom_checkbox);
|
||||
nocdrom_checkbox->SetValue(PrefsFindBool("nocdrom") ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create "Graphics/Sound" pane
|
||||
*/
|
||||
|
||||
struct video_mode_box {
|
||||
uint32 mode;
|
||||
int mode_string_id, bit_string_id;
|
||||
float left, top;
|
||||
BCheckBox *box;
|
||||
};
|
||||
|
||||
const int NUM_WINDOW_MODES = 6;
|
||||
const int NUM_SCREEN_MODES = 18;
|
||||
|
||||
static video_mode_box window_mode_boxes[NUM_SCREEN_MODES] = {
|
||||
{B_8_BIT_640x480, STR_W_640x480_CTRL, STR_8_BIT_CTRL, 140, 48, NULL},
|
||||
{B_15_BIT_640x480, STR_W_640x480_CTRL, STR_16_BIT_CTRL, 220, 48, NULL},
|
||||
{B_32_BIT_640x480, STR_W_640x480_CTRL, STR_32_BIT_CTRL, 300, 48, NULL},
|
||||
{B_8_BIT_800x600, STR_W_800x600_CTRL, STR_8_BIT_CTRL, 140, 65, NULL},
|
||||
{B_15_BIT_800x600, STR_W_800x600_CTRL, STR_16_BIT_CTRL, 220, 65, NULL},
|
||||
{B_32_BIT_800x600, STR_W_800x600_CTRL, STR_32_BIT_CTRL, 300, 65, NULL},
|
||||
};
|
||||
|
||||
static video_mode_box screen_mode_boxes[NUM_SCREEN_MODES] = {
|
||||
{B_8_BIT_640x480, STR_640x480_CTRL, STR_8_BIT_CTRL, 140, 82, NULL},
|
||||
{B_15_BIT_640x480, STR_640x480_CTRL, STR_16_BIT_CTRL, 220, 82, NULL},
|
||||
{B_32_BIT_640x480, STR_640x480_CTRL, STR_32_BIT_CTRL, 300, 82, NULL},
|
||||
{B_8_BIT_800x600, STR_800x600_CTRL, STR_8_BIT_CTRL, 140, 99, NULL},
|
||||
{B_15_BIT_800x600, STR_800x600_CTRL, STR_16_BIT_CTRL, 220, 99, NULL},
|
||||
{B_32_BIT_800x600, STR_800x600_CTRL, STR_32_BIT_CTRL, 300, 99, NULL},
|
||||
{B_8_BIT_1024x768, STR_1024x768_CTRL, STR_8_BIT_CTRL, 140, 116, NULL},
|
||||
{B_15_BIT_1024x768, STR_1024x768_CTRL, STR_16_BIT_CTRL, 220, 116, NULL},
|
||||
{B_32_BIT_1024x768, STR_1024x768_CTRL, STR_32_BIT_CTRL, 300, 116, NULL},
|
||||
{B_8_BIT_1152x900, STR_1152x900_CTRL, STR_8_BIT_CTRL, 140, 133, NULL},
|
||||
{B_15_BIT_1152x900, STR_1152x900_CTRL, STR_16_BIT_CTRL, 220, 133, NULL},
|
||||
{B_32_BIT_1152x900, STR_1152x900_CTRL, STR_32_BIT_CTRL, 300, 133, NULL},
|
||||
{B_8_BIT_1280x1024, STR_1280x1024_CTRL, STR_8_BIT_CTRL, 140, 150, NULL},
|
||||
{B_15_BIT_1280x1024, STR_1280x1024_CTRL, STR_16_BIT_CTRL, 220, 150, NULL},
|
||||
{B_32_BIT_1280x1024, STR_1280x1024_CTRL, STR_32_BIT_CTRL, 300, 150, NULL},
|
||||
{B_8_BIT_1600x1200, STR_1600x1200_CTRL, STR_8_BIT_CTRL, 140, 167, NULL},
|
||||
{B_15_BIT_1600x1200, STR_1600x1200_CTRL, STR_16_BIT_CTRL, 220, 167, NULL},
|
||||
{B_32_BIT_1600x1200, STR_1600x1200_CTRL, STR_32_BIT_CTRL, 300, 167, NULL}
|
||||
};
|
||||
|
||||
BView *PrefsWindow::create_graphics_pane(void)
|
||||
{
|
||||
BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_GRAPHICS_SOUND_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
pane->SetViewColor(fill_color);
|
||||
float right = pane->Bounds().right-10;
|
||||
|
||||
BMenuField *menu_field;
|
||||
BPopUpMenu *menu = new BPopUpMenu("");
|
||||
menu_field = new BMenuField(BRect(10, 5, right, 20), "frameskip", GetString(STR_FRAMESKIP_CTRL), menu);
|
||||
menu_field->SetDivider(120);
|
||||
menu->AddItem(new BMenuItem(GetString(STR_REF_5HZ_LAB), new BMessage(MSG_REF_5HZ)));
|
||||
menu->AddItem(new BMenuItem(GetString(STR_REF_7_5HZ_LAB), new BMessage(MSG_REF_7_5HZ)));
|
||||
menu->AddItem(new BMenuItem(GetString(STR_REF_10HZ_LAB), new BMessage(MSG_REF_10HZ)));
|
||||
menu->AddItem(new BMenuItem(GetString(STR_REF_15HZ_LAB), new BMessage(MSG_REF_15HZ)));
|
||||
menu->AddItem(new BMenuItem(GetString(STR_REF_30HZ_LAB), new BMessage(MSG_REF_30HZ)));
|
||||
pane->AddChild(menu_field);
|
||||
int32 i32 = PrefsFindInt32("frameskip");
|
||||
BMenuItem *item;
|
||||
if (i32 == 12) {
|
||||
if ((item = menu->FindItem(GetString(STR_REF_5HZ_LAB))) != NULL)
|
||||
item->SetMarked(true);
|
||||
} else if (i32 == 8) {
|
||||
if ((item = menu->FindItem(GetString(STR_REF_7_5HZ_LAB))) != NULL)
|
||||
item->SetMarked(true);
|
||||
} else if (i32 == 6) {
|
||||
if ((item = menu->FindItem(GetString(STR_REF_10HZ_LAB))) != NULL)
|
||||
item->SetMarked(true);
|
||||
} else if (i32 == 4) {
|
||||
if ((item = menu->FindItem(GetString(STR_REF_15HZ_LAB))) != NULL)
|
||||
item->SetMarked(true);
|
||||
} else if (i32 == 2) {
|
||||
if ((item = menu->FindItem(GetString(STR_REF_30HZ_LAB))) != NULL)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
|
||||
gfxaccel_checkbox = new BCheckBox(BRect(10, 25, right, 40), "gfxaccel", GetString(STR_GFXACCEL_CTRL), new BMessage(MSG_GFXACCEL));
|
||||
pane->AddChild(gfxaccel_checkbox);
|
||||
gfxaccel_checkbox->SetValue(PrefsFindBool("gfxaccel") ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
|
||||
uint32 window_modes = PrefsFindInt32("windowmodes");
|
||||
for (int i=0; i<NUM_WINDOW_MODES; i++) {
|
||||
video_mode_box *p = window_mode_boxes + i;
|
||||
if (p->bit_string_id == STR_8_BIT_CTRL) {
|
||||
BStringView *text = new BStringView(BRect(10, p->top, 120, p->top + 15), "", GetString(p->mode_string_id));
|
||||
pane->AddChild(text);
|
||||
}
|
||||
p->box = new BCheckBox(BRect(p->left, p->top, p->left + 80, p->top + 15), "", GetString(p->bit_string_id), new BMessage(MSG_WINDOW_MODE));
|
||||
pane->AddChild(p->box);
|
||||
p->box->SetValue(window_modes & p->mode ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
}
|
||||
uint32 screen_modes = PrefsFindInt32("screenmodes");
|
||||
for (int i=0; i<NUM_SCREEN_MODES; i++) {
|
||||
video_mode_box *p = screen_mode_boxes + i;
|
||||
if (p->bit_string_id == STR_8_BIT_CTRL) {
|
||||
BStringView *text = new BStringView(BRect(10, p->top, 120, p->top + 15), "", GetString(p->mode_string_id));
|
||||
pane->AddChild(text);
|
||||
}
|
||||
p->box = new BCheckBox(BRect(p->left, p->top, p->left + 80, p->top + 15), "", GetString(p->bit_string_id), new BMessage(MSG_SCREEN_MODE));
|
||||
pane->AddChild(p->box);
|
||||
p->box->SetValue(screen_modes & p->mode ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
}
|
||||
|
||||
nosound_checkbox = new BCheckBox(BRect(10, 185, right, 200), "nosound", GetString(STR_NOSOUND_CTRL), new BMessage(MSG_NOSOUND));
|
||||
pane->AddChild(nosound_checkbox);
|
||||
nosound_checkbox->SetValue(PrefsFindBool("nosound") ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create "Serial/Network" pane
|
||||
*/
|
||||
|
||||
static void add_serial_names(BPopUpMenu *menu, uint32 msg)
|
||||
{
|
||||
BSerialPort *port = new BSerialPort;
|
||||
char name[B_PATH_NAME_LENGTH];
|
||||
for (int i=0; i<port->CountDevices(); i++) {
|
||||
port->GetDeviceName(i, name);
|
||||
menu->AddItem(new BMenuItem(name, new BMessage(msg)));
|
||||
}
|
||||
if (SysInfo.platform_type == B_BEBOX_PLATFORM) {
|
||||
BDirectory dir;
|
||||
BEntry entry;
|
||||
dir.SetTo("/dev/parallel");
|
||||
if (dir.InitCheck() == B_NO_ERROR) {
|
||||
dir.Rewind();
|
||||
while (dir.GetNextEntry(&entry) >= 0) {
|
||||
if (!entry.IsDirectory()) {
|
||||
entry.GetName(name);
|
||||
menu->AddItem(new BMenuItem(name, new BMessage(msg)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete port;
|
||||
}
|
||||
|
||||
static void set_serial_label(BPopUpMenu *menu, const char *prefs_name)
|
||||
{
|
||||
const char *str;
|
||||
BMenuItem *item;
|
||||
if ((str = PrefsFindString(prefs_name)) != NULL)
|
||||
if ((item = menu->FindItem(str)) != NULL)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
|
||||
BView *PrefsWindow::create_serial_pane(void)
|
||||
{
|
||||
BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_SERIAL_NETWORK_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
pane->SetViewColor(fill_color);
|
||||
float right = pane->Bounds().right-10;
|
||||
|
||||
BMenuField *menu_field;
|
||||
BPopUpMenu *menu_a = new BPopUpMenu("");
|
||||
add_serial_names(menu_a, MSG_SER_A);
|
||||
menu_field = new BMenuField(BRect(10, 5, right, 20), "seriala", GetString(STR_SERPORTA_CTRL), menu_a);
|
||||
menu_field->SetDivider(90);
|
||||
pane->AddChild(menu_field);
|
||||
set_serial_label(menu_a, "seriala");
|
||||
|
||||
BPopUpMenu *menu_b = new BPopUpMenu("");
|
||||
add_serial_names(menu_b, MSG_SER_B);
|
||||
menu_field = new BMenuField(BRect(10, 26, right, 41), "serialb", GetString(STR_SERPORTB_CTRL), menu_b);
|
||||
menu_field->SetDivider(90);
|
||||
pane->AddChild(menu_field);
|
||||
set_serial_label(menu_b, "serialb");
|
||||
|
||||
nonet_checkbox = new BCheckBox(BRect(10, 47, right, 62), "nonet", GetString(STR_NONET_CTRL), new BMessage(MSG_NONET));
|
||||
pane->AddChild(nonet_checkbox);
|
||||
nonet_checkbox->SetValue(PrefsFindBool("nonet") ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create "Memory/Misc" pane
|
||||
*/
|
||||
|
||||
BView *PrefsWindow::create_memory_pane(void)
|
||||
{
|
||||
char str[256], str2[256];
|
||||
BView *pane = new BView(BRect(0, 0, top_frame.right-20, top_frame.bottom-80), GetString(STR_MEMORY_MISC_PANE_TITLE), B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
pane->SetViewColor(fill_color);
|
||||
float right = pane->Bounds().right-10;
|
||||
|
||||
BEntry entry("/boot/var/swap");
|
||||
off_t swap_space;
|
||||
if (entry.GetSize(&swap_space) == B_NO_ERROR)
|
||||
max_ramsize = swap_space / (1024 * 1024) - 8;
|
||||
else
|
||||
max_ramsize = SysInfo.max_pages * B_PAGE_SIZE / (1024 * 1024) - 8;
|
||||
|
||||
int32 value = PrefsFindInt32("ramsize") / (1024 * 1024);
|
||||
|
||||
ramsize_slider = new RAMSlider(BRect(10, 5, right, 55), "ramsize", GetString(STR_RAMSIZE_SLIDER), new BMessage(MSG_RAMSIZE), 8, max_ramsize, B_TRIANGLE_THUMB);
|
||||
ramsize_slider->SetValue(value);
|
||||
ramsize_slider->UseFillColor(true, &slider_fill_color);
|
||||
sprintf(str, GetString(STR_RAMSIZE_FMT), 8);
|
||||
sprintf(str2, GetString(STR_RAMSIZE_FMT), max_ramsize);
|
||||
ramsize_slider->SetLimitLabels(str, str2);
|
||||
pane->AddChild(ramsize_slider);
|
||||
|
||||
ignoresegv_checkbox = new BCheckBox(BRect(10, 60, right, 75), "ignoresegv", GetString(STR_IGNORESEGV_CTRL), new BMessage(MSG_IGNORESEGV));
|
||||
pane->AddChild(ignoresegv_checkbox);
|
||||
ignoresegv_checkbox->SetValue(PrefsFindBool("ignoresegv") ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
|
||||
idlewait_checkbox = new BCheckBox(BRect(10, 80, right, 95), "idlewait", GetString(STR_IDLEWAIT_CTRL), new BMessage(MSG_IDLEWAIT));
|
||||
pane->AddChild(idlewait_checkbox);
|
||||
idlewait_checkbox->SetValue(PrefsFindBool("idlewait") ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||
|
||||
rom_control = new PathControl(false, BRect(10, 100, right, 115), "rom", GetString(STR_ROM_FILE_CTRL), PrefsFindString("rom"), NULL);
|
||||
rom_control->SetDivider(117);
|
||||
pane->AddChild(rom_control);
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Message from controls/menus received
|
||||
*/
|
||||
|
||||
void PrefsWindow::MessageReceived(BMessage *msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case MSG_OK: // "Start" button clicked
|
||||
PrefsReplaceString("extfs", extfs_control->Text());
|
||||
const char *str = rom_control->Text();
|
||||
if (strlen(str))
|
||||
PrefsReplaceString("rom", str);
|
||||
else
|
||||
PrefsRemoveItem("rom");
|
||||
SavePrefs();
|
||||
send_quit_on_close = false;
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
be_app->PostMessage(ok_message);
|
||||
break;
|
||||
|
||||
case MSG_CANCEL: // "Quit" button clicked
|
||||
send_quit_on_close = false;
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
|
||||
case B_ABOUT_REQUESTED: // "About" menu item selected
|
||||
OpenAboutWindow();
|
||||
break;
|
||||
|
||||
case MSG_ZAP_PRAM: // "Zap PRAM File" menu item selected
|
||||
ZapPRAM();
|
||||
break;
|
||||
|
||||
case MSG_VOLUME_INVOKED: { // Double-clicked on volume name, toggle read-only flag
|
||||
int selected = volume_list->CurrentSelection();
|
||||
if (selected >= 0) {
|
||||
const char *str = PrefsFindString("disk", selected);
|
||||
BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected);
|
||||
delete item;
|
||||
char newstr[256];
|
||||
if (str[0] == '*')
|
||||
strcpy(newstr, str+1);
|
||||
else {
|
||||
strcpy(newstr, "*");
|
||||
strcat(newstr, str);
|
||||
}
|
||||
PrefsReplaceString("disk", newstr, selected);
|
||||
volume_list->AddItem(new BStringItem(newstr), selected);
|
||||
volume_list->Select(selected);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_ADD_VOLUME:
|
||||
add_volume_panel->Show();
|
||||
break;
|
||||
|
||||
case MSG_CREATE_VOLUME:
|
||||
create_volume_panel->Show();
|
||||
break;
|
||||
|
||||
case MSG_ADD_VOLUME_PANEL: {
|
||||
entry_ref ref;
|
||||
if (msg->FindRef("refs", &ref) == B_NO_ERROR) {
|
||||
BEntry entry(&ref, true);
|
||||
BPath path;
|
||||
entry.GetPath(&path);
|
||||
if (entry.IsFile()) {
|
||||
PrefsAddString("disk", path.Path());
|
||||
volume_list->AddItem(new BStringItem(path.Path()));
|
||||
} else if (entry.IsDirectory()) {
|
||||
BVolume volume;
|
||||
if (path.Path()[0] == '/' && strchr(path.Path()+1, '/') == NULL && entry.GetVolume(&volume) == B_NO_ERROR) {
|
||||
int32 i = 0;
|
||||
dev_t d;
|
||||
fs_info info;
|
||||
while ((d = next_dev(&i)) >= 0) {
|
||||
fs_stat_dev(d, &info);
|
||||
if (volume.Device() == info.dev) {
|
||||
PrefsAddString("disk", info.device_name);
|
||||
volume_list->AddItem(new BStringItem(info.device_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_CREATE_VOLUME_PANEL: {
|
||||
entry_ref dir;
|
||||
if (msg->FindRef("directory", &dir) == B_NO_ERROR) {
|
||||
BEntry entry(&dir, true);
|
||||
BPath path;
|
||||
entry.GetPath(&path);
|
||||
path.Append(msg->FindString("name"));
|
||||
|
||||
create_volume_panel->Window()->Lock();
|
||||
BView *background = create_volume_panel->Window()->ChildAt(0);
|
||||
NumberControl *v = (NumberControl *)background->FindView("hardfile_size");
|
||||
int size = v->Value();
|
||||
|
||||
char cmd[1024];
|
||||
sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", path.Path(), size);
|
||||
int ret = system(cmd);
|
||||
if (ret == 0) {
|
||||
PrefsAddString("disk", path.Path());
|
||||
volume_list->AddItem(new BStringItem(path.Path()));
|
||||
} else {
|
||||
sprintf(cmd, GetString(STR_CREATE_VOLUME_WARN), strerror(ret));
|
||||
WarningAlert(cmd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_REMOVE_VOLUME: {
|
||||
int selected = volume_list->CurrentSelection();
|
||||
if (selected >= 0) {
|
||||
PrefsRemoveItem("disk", selected);
|
||||
BStringItem *item = (BStringItem *)volume_list->RemoveItem(selected);
|
||||
delete item;
|
||||
volume_list->Select(selected);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_BOOT_ANY:
|
||||
PrefsReplaceInt32("bootdriver", 0);
|
||||
break;
|
||||
|
||||
case MSG_BOOT_CDROM:
|
||||
PrefsReplaceInt32("bootdriver", CDROMRefNum);
|
||||
break;
|
||||
|
||||
case MSG_NOCDROM:
|
||||
PrefsReplaceBool("nocdrom", nocdrom_checkbox->Value() == B_CONTROL_ON);
|
||||
break;
|
||||
|
||||
case MSG_GFXACCEL:
|
||||
PrefsReplaceBool("gfxaccel", gfxaccel_checkbox->Value() == B_CONTROL_ON);
|
||||
break;
|
||||
|
||||
case MSG_NOSOUND:
|
||||
PrefsReplaceBool("nosound", nosound_checkbox->Value() == B_CONTROL_ON);
|
||||
break;
|
||||
|
||||
case MSG_WINDOW_MODE: {
|
||||
BCheckBox *source = NULL;
|
||||
msg->FindPointer("source", &source);
|
||||
if (source == NULL)
|
||||
break;
|
||||
for (int i=0; i<NUM_WINDOW_MODES; i++) {
|
||||
video_mode_box *p = window_mode_boxes + i;
|
||||
if (p->box == source) {
|
||||
if (p->box->Value() == B_CONTROL_ON)
|
||||
PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") | p->mode);
|
||||
else
|
||||
PrefsReplaceInt32("windowmodes", PrefsFindInt32("windowmodes") & ~(p->mode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_SCREEN_MODE: {
|
||||
BCheckBox *source = NULL;
|
||||
msg->FindPointer("source", &source);
|
||||
if (source == NULL)
|
||||
break;
|
||||
for (int i=0; i<NUM_SCREEN_MODES; i++) {
|
||||
video_mode_box *p = screen_mode_boxes + i;
|
||||
if (p->box == source) {
|
||||
if (p->box->Value() == B_CONTROL_ON)
|
||||
PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") | p->mode);
|
||||
else
|
||||
PrefsReplaceInt32("screenmodes", PrefsFindInt32("screenmodes") & ~(p->mode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_REF_5HZ:
|
||||
PrefsReplaceInt32("frameskip", 12);
|
||||
break;
|
||||
|
||||
case MSG_REF_7_5HZ:
|
||||
PrefsReplaceInt32("frameskip", 8);
|
||||
break;
|
||||
|
||||
case MSG_REF_10HZ:
|
||||
PrefsReplaceInt32("frameskip", 6);
|
||||
break;
|
||||
|
||||
case MSG_REF_15HZ:
|
||||
PrefsReplaceInt32("frameskip", 4);
|
||||
break;
|
||||
|
||||
case MSG_REF_30HZ:
|
||||
PrefsReplaceInt32("frameskip", 2);
|
||||
break;
|
||||
|
||||
case MSG_SER_A: {
|
||||
BMenuItem *source = NULL;
|
||||
msg->FindPointer("source", &source);
|
||||
if (source)
|
||||
PrefsReplaceString("seriala", source->Label());
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_SER_B: {
|
||||
BMenuItem *source = NULL;
|
||||
msg->FindPointer("source", &source);
|
||||
if (source)
|
||||
PrefsReplaceString("serialb", source->Label());
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_NONET:
|
||||
PrefsReplaceBool("nonet", nonet_checkbox->Value() == B_CONTROL_ON);
|
||||
break;
|
||||
|
||||
case MSG_IGNORESEGV:
|
||||
PrefsReplaceBool("ignoresegv", ignoresegv_checkbox->Value() == B_CONTROL_ON);
|
||||
break;
|
||||
|
||||
case MSG_IDLEWAIT:
|
||||
PrefsReplaceBool("idlewait", idlewait_checkbox->Value() == B_CONTROL_ON);
|
||||
break;
|
||||
|
||||
case MSG_RAMSIZE:
|
||||
PrefsReplaceInt32("ramsize", ramsize_slider->Value() * 1024 * 1024);
|
||||
break;
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(msg);
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../../../BasiliskII/src/BeOS/scsi_beos.cpp
|
|
@ -1 +0,0 @@
|
|||
../../../BasiliskII/src/BeOS/serial_beos.cpp
|
|
@ -1 +0,0 @@
|
|||
../../../BasiliskII/src/BeOS/sys_beos.cpp
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* sysdeps.h - System dependent definitions for BeOS
|
||||
*
|
||||
* SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SYSDEPS_H
|
||||
#define SYSDEPS_H
|
||||
|
||||
// Do we have std namespace?
|
||||
#ifdef __POWERPC__
|
||||
#define NO_STD_NAMESPACE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <KernelKit.h>
|
||||
|
||||
#include "user_strings_beos.h"
|
||||
|
||||
// Are we using a PPC emulator or the real thing?
|
||||
#ifdef __POWERPC__
|
||||
#define EMULATED_PPC 0
|
||||
#define WORDS_BIGENDIAN 1
|
||||
#define SYSTEM_CLOBBERS_R2 1
|
||||
#else
|
||||
#define EMULATED_PPC 1
|
||||
#undef WORDS_BIGENDIAN
|
||||
#endif
|
||||
|
||||
// High precision timing
|
||||
#define PRECISE_TIMING 1
|
||||
#define PRECISE_TIMING_BEOS 1
|
||||
|
||||
#define POWERPC_ROM 1
|
||||
|
||||
// Time data type for Time Manager emulation
|
||||
typedef bigtime_t tm_time_t;
|
||||
|
||||
// 64 bit file offsets
|
||||
typedef off_t loff_t;
|
||||
|
||||
// Data types
|
||||
typedef uint32 uintptr;
|
||||
typedef int32 intptr;
|
||||
|
||||
// Timing functions
|
||||
extern void Delay_usec(uint32 usec);
|
||||
|
||||
// Macro for calling MacOS routines
|
||||
#define CallMacOS(type, proc) (*(type)proc)()
|
||||
#define CallMacOS1(type, proc, arg1) (*(type)proc)(arg1)
|
||||
#define CallMacOS2(type, proc, arg1, arg2) (*(type)proc)(arg1, arg2)
|
||||
#define CallMacOS3(type, proc, arg1, arg2, arg3) (*(type)proc)(arg1, arg2, arg3)
|
||||
#define CallMacOS4(type, proc, arg1, arg2, arg3, arg4) (*(type)proc)(arg1, arg2, arg3, arg4)
|
||||
#define CallMacOS5(type, proc, arg1, arg2, arg3, arg4, arg5) (*(type)proc)(arg1, arg2, arg3, arg4, arg5)
|
||||
#define CallMacOS6(type, proc, arg1, arg2, arg3, arg4, arg5, arg6) (*(type)proc)(arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
#define CallMacOS7(type, proc, arg1, arg2, arg3, arg4, arg5, arg6, arg7) (*(type)proc)(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user