Remove support for all other platforms other than macOS

This commit is contained in:
uyjulian 2018-04-15 11:17:57 -05:00
parent b58a9260bd
commit c4b1b1937e
No known key found for this signature in database
GPG Key ID: FEA459A8CA14685B
334 changed files with 198 additions and 120731 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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"));
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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)
{
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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)
{
}

View File

@ -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;
}
}

View File

@ -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"));
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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;
}

View File

@ -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

View File

@ -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());
}

File diff suppressed because it is too large Load Diff

View File

@ -498,7 +498,7 @@ bool Screen_blitter_init(VisualFormat const & visual_format, bool native_byte_or
#else
const bool use_sdl_video = false;
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
#if DIRECT_ADDRESSING
if (mac_depth == 1 && !use_sdl_video && !visual_format.fullscreen) {
// Windowed 1-bit mode uses a 1-bit X image, so there's no need for special blitting routines

View File

@ -26,9 +26,6 @@
#include "sigsegv.h"
#include "vm_alloc.h"
#ifdef _WIN32
#include "util_windows.h"
#endif
// Glue for SDL and X11 support
#ifdef TEST_VOSF_PERFORMANCE
@ -180,10 +177,6 @@ static inline unsigned find_next_page_clear(unsigned page)
static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect frame buffer (dirtyPages in fact)
#define LOCK_VOSF pthread_mutex_lock(&vosf_lock);
#define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock);
#elif defined(_WIN32)
static mutex_t vosf_lock; // Mutex to protect frame buffer (dirtyPages in fact)
#define LOCK_VOSF vosf_lock.lock();
#define UNLOCK_VOSF vosf_lock.unlock();
#elif defined(HAVE_SPINLOCKS)
static spinlock_t vosf_lock = SPIN_LOCK_UNLOCKED; // Mutex to protect frame buffer (dirtyPages in fact)
#define LOCK_VOSF spin_lock(&vosf_lock)
@ -533,7 +526,7 @@ static void update_display_window_vosf(VIDEO_DRV_WIN_INIT)
*/
#ifndef TEST_VOSF_PERFORMANCE
#if REAL_ADDRESSING || DIRECT_ADDRESSING
#if DIRECT_ADDRESSING
static void update_display_dga_vosf(VIDEO_DRV_DGA_INIT)
{
VIDEO_MODE_INIT;

View File

@ -27,11 +27,6 @@
#include <fcntl.h>
#endif
#ifdef HAVE_WIN32_VM
#define WIN32_LEAN_AND_MEAN /* avoid including junk */
#include <windows.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -53,13 +48,8 @@
#endif
#endif
#ifdef HAVE_WIN32_VM
/* Windows is either ILP32 or LLP64 */
typedef UINT_PTR vm_uintptr_t;
#else
/* Other systems are sane as they are either ILP32 or LP64 */
typedef unsigned long vm_uintptr_t;
#endif
/* We want MAP_32BIT, if available, for SheepShaver and BasiliskII
because the emulated target is 32-bit and this helps to allocate
@ -71,11 +61,7 @@ typedef unsigned long vm_uintptr_t;
#ifndef MAP_32BIT
#define MAP_32BIT 0
#endif
#ifdef __FreeBSD__
#define FORCE_MAP_32BIT MAP_FIXED
#else
#define FORCE_MAP_32BIT MAP_32BIT
#endif
#ifndef MAP_ANON
#define MAP_ANON 0
#endif
@ -86,10 +72,9 @@ typedef unsigned long vm_uintptr_t;
#define MAP_EXTRA_FLAGS (MAP_32BIT)
#ifdef HAVE_MMAP_VM
#if (defined(__linux__) && defined(__i386__)) || defined(__FreeBSD__) || HAVE_LINKER_SCRIPT
#if HAVE_LINKER_SCRIPT
/* Force a reasonnable address below 0x80000000 on x86 so that we
don't get addresses above when the program is run on AMD64.
NOTE: this is empirically determined on Linux/x86. */
don't get addresses above when the program is run on AMD64. */
#define MAP_BASE 0x10000000
#else
#define MAP_BASE 0x00000000
@ -127,40 +112,6 @@ static int translate_map_flags(int vm_flags)
}
#endif
/* Align ADDR and SIZE to 64K boundaries. */
#ifdef HAVE_WIN32_VM
static inline LPVOID align_addr_segment(LPVOID addr)
{
return LPVOID(vm_uintptr_t(addr) & ~vm_uintptr_t(0xFFFF));
}
static inline DWORD align_size_segment(LPVOID addr, DWORD size)
{
return size + ((vm_uintptr_t)addr - (vm_uintptr_t)align_addr_segment(addr));
}
#endif
/* Translate generic VM prot flags to host values. */
#ifdef HAVE_WIN32_VM
static int translate_prot_flags(int prot_flags)
{
int prot = PAGE_READWRITE;
if (prot_flags == (VM_PAGE_EXECUTE | VM_PAGE_READ | VM_PAGE_WRITE))
prot = PAGE_EXECUTE_READWRITE;
else if (prot_flags == (VM_PAGE_EXECUTE | VM_PAGE_READ))
prot = PAGE_EXECUTE_READ;
else if (prot_flags == (VM_PAGE_READ | VM_PAGE_WRITE))
prot = PAGE_READWRITE;
else if (prot_flags == VM_PAGE_READ)
prot = PAGE_READONLY;
else if (prot_flags == 0)
prot = PAGE_NOACCESS;
return prot;
}
#endif
/* Translate Mach return codes to POSIX errno values. */
#ifdef HAVE_MACH_VM
static int vm_error(kern_return_t ret_code)
@ -193,17 +144,17 @@ int vm_init(void)
// On 10.4 and earlier, reset CrashReporter's task signal handler to
// avoid having it show up for signals that get handled.
#if defined(__APPLE__) && defined(__MACH__)
struct utsname info;
// #if defined(__APPLE__) && defined(__MACH__)
// struct utsname info;
if (!uname(&info) && atoi(info.release) <= 8) {
task_set_exception_ports(mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC,
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
}
#endif
// if (!uname(&info) && atoi(info.release) <= 8) {
// task_set_exception_ports(mach_task_self(),
// EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC,
// MACH_PORT_NULL,
// EXCEPTION_STATE_IDENTITY,
// MACHINE_THREAD_STATE);
// }
// #endif
return 0;
}
@ -260,13 +211,6 @@ void * vm_acquire(size_t size, int options)
return VM_MAP_FAILED;
next_address = (char *)addr + size;
#elif defined(HAVE_WIN32_VM)
int alloc_type = MEM_RESERVE | MEM_COMMIT;
if (options & VM_MAP_WRITE_WATCH)
alloc_type |= MEM_WRITE_WATCH;
if ((addr = VirtualAlloc(NULL, size, alloc_type, PAGE_EXECUTE_READWRITE)) == NULL)
return VM_MAP_FAILED;
#else
if ((addr = calloc(size, 1)) == 0)
return VM_MAP_FAILED;
@ -312,21 +256,6 @@ int vm_acquire_fixed(void * addr, size_t size, int options)
if (mmap((caddr_t)addr, size, VM_PAGE_DEFAULT, the_map_flags, fd, 0) == (void *)MAP_FAILED)
return -1;
#elif defined(HAVE_WIN32_VM)
// Windows cannot allocate Low Memory
if (addr == NULL)
return -1;
int alloc_type = MEM_RESERVE | MEM_COMMIT;
if (options & VM_MAP_WRITE_WATCH)
alloc_type |= MEM_WRITE_WATCH;
// Allocate a possibly offset region to align on 64K boundaries
LPVOID req_addr = align_addr_segment(addr);
DWORD req_size = align_size_segment(addr, size);
LPVOID ret_addr = VirtualAlloc(req_addr, req_size, alloc_type, PAGE_EXECUTE_READWRITE);
if (ret_addr != req_addr)
return -1;
#else
// Unsupported
return -1;
@ -356,14 +285,9 @@ int vm_release(void * addr, size_t size)
#ifdef HAVE_MMAP_VM
if (munmap((caddr_t)addr, size) != 0)
return -1;
#else
#ifdef HAVE_WIN32_VM
if (VirtualFree(align_addr_segment(addr), 0, MEM_RELEASE) == 0)
return -1;
#else
free(addr);
#endif
#endif
#endif
return 0;
@ -381,17 +305,11 @@ int vm_protect(void * addr, size_t size, int prot)
#ifdef HAVE_MMAP_VM
int ret_code = mprotect((caddr_t)addr, size, prot);
return ret_code == 0 ? 0 : -1;
#else
#ifdef HAVE_WIN32_VM
DWORD old_prot;
int ret_code = VirtualProtect(addr, size, translate_prot_flags(prot), &old_prot);
return ret_code != 0 ? 0 : -1;
#else
// Unsupported
return -1;
#endif
#endif
#endif
}
/* Return the addresses of the pages that got modified in the
@ -403,20 +321,7 @@ int vm_get_write_watch(void * addr, size_t size,
int options)
{
#ifdef HAVE_VM_WRITE_WATCH
#ifdef HAVE_WIN32_VM
DWORD flags = 0;
if (options & VM_WRITE_WATCH_RESET)
flags |= WRITE_WATCH_FLAG_RESET;
ULONG page_size;
ULONG_PTR count = *n_pages;
int ret_code = GetWriteWatch(flags, addr, size, pages, &count, &page_size);
if (ret_code != 0)
return -1;
*n_pages = count;
return 0;
#endif
#endif
// Unsupported
return -1;
@ -428,10 +333,7 @@ int vm_get_write_watch(void * addr, size_t size,
int vm_reset_write_watch(void * addr, size_t size)
{
#ifdef HAVE_VM_WRITE_WATCH
#ifdef HAVE_WIN32_VM
int ret_code = ResetWriteWatch(addr, size);
return ret_code == 0 ? 0 : -1;
#endif
#endif
// Unsupported
return -1;
@ -441,17 +343,7 @@ int vm_reset_write_watch(void * addr, size_t size)
int vm_get_page_size(void)
{
#ifdef HAVE_WIN32_VM
static vm_uintptr_t page_size = 0;
if (page_size == 0) {
SYSTEM_INFO si;
GetSystemInfo(&si);
page_size = si.dwAllocationGranularity;
}
return page_size;
#else
return getpagesize();
#endif
}
#ifdef CONFIGURE_TEST_VM_WRITE_WATCH

View File

@ -1,307 +0,0 @@
/*
*
* This is based on Apple example software AudioBackEnd.cpp
*
* Copyright © 2004 Apple Computer, Inc., All Rights Reserved
* Original Apple code modified by Daniel Sumorok
*
* 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 "AudioBackEnd.h"
#pragma mark ---Public Methods---
AudioBackEnd::AudioBackEnd(int bitsPerSample, int numChannels, int sampleRate):
mBitsPerSample(bitsPerSample),
mSampleRate(sampleRate),
mNumChannels(numChannels),
mCallback(NULL),
mCallbackArg(NULL),
mBufferSizeFrames(0),
mFramesProcessed(0),
mAudioBuffer(NULL),
mAudioBufferWriteIndex(0),
mAudioBufferReadIndex(0),
mBytesPerFrame(0),
mAudioBufferSize(0) {
OSStatus err = noErr;
err = Init();
if(err) {
fprintf(stderr,"AudioBackEnd ERROR: Cannot Init AudioBackEnd");
exit(1);
}
}
AudioBackEnd::~AudioBackEnd() { //clean up
Stop();
AUGraphClose(mGraph);
DisposeAUGraph(mGraph);
if(mAudioBuffer != NULL) {
delete mAudioBuffer;
mAudioBuffer = NULL;
mAudioBufferSize = 0;
}
}
OSStatus AudioBackEnd::Init() {
OSStatus err = noErr;
err = SetupGraph();
checkErr(err);
err = SetupBuffers();
checkErr(err);
err = AUGraphInitialize(mGraph);
checkErr(err);
return err;
}
#pragma mark --- Operation---
OSStatus AudioBackEnd::Start()
{
OSStatus err = noErr;
if(!IsRunning()) {
mFramesProcessed = 0;
mAudioBufferWriteIndex = 0;
mAudioBufferReadIndex = 0;
err = AUGraphStart(mGraph);
}
return err;
}
OSStatus AudioBackEnd::Stop() {
OSStatus err = noErr;
if(IsRunning()) {
err = AUGraphStop(mGraph);
}
return err;
}
Boolean AudioBackEnd::IsRunning() {
OSStatus err = noErr;
Boolean graphRunning;
err = AUGraphIsRunning(mGraph,&graphRunning);
return (graphRunning);
}
#pragma mark -
#pragma mark --Private methods---
OSStatus AudioBackEnd::SetupGraph() {
OSStatus err = noErr;
AURenderCallbackStruct output;
UInt32 size;
ComponentDescription outDesc;
AudioDeviceID out;
//Make a New Graph
err = NewAUGraph(&mGraph);
checkErr(err);
//Open the Graph, AudioUnits are opened but not initialized
err = AUGraphOpen(mGraph);
checkErr(err);
outDesc.componentType = kAudioUnitType_Output;
outDesc.componentSubType = kAudioUnitSubType_DefaultOutput;
outDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
outDesc.componentFlags = 0;
outDesc.componentFlagsMask = 0;
//////////////////////////
///MAKE NODES
//This creates a node in the graph that is an AudioUnit, using
//the supplied ComponentDescription to find and open that unit
err = AUGraphNewNode(mGraph, &outDesc, 0, NULL, &mOutputNode);
checkErr(err);
//Get Audio Units from AUGraph node
err = AUGraphGetNodeInfo(mGraph, mOutputNode, NULL, NULL, NULL, &mOutputUnit);
checkErr(err);
err = AUGraphUpdate(mGraph, NULL);
checkErr(err);
size = sizeof(AudioDeviceID);
err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
&size, &out);
checkErr(err);
mOutputDevice.Init(out, false);
//Set the Current Device to the Default Output Unit.
err = AudioUnitSetProperty(mOutputUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global,
0,
&out,
sizeof(out));
checkErr(err);
output.inputProc = OutputProc;
output.inputProcRefCon = this;
err = AudioUnitSetProperty(mOutputUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&output,
sizeof(output));
checkErr(err);
return err;
}
//Allocate Audio Buffer List(s) to hold the data from input.
OSStatus AudioBackEnd::SetupBuffers() {
OSStatus err = noErr;
UInt32 safetyOffset;
AudioStreamBasicDescription asbd;
UInt32 propertySize;
propertySize = sizeof(mBufferSizeFrames);
err = AudioUnitGetProperty(mOutputUnit, kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global, 0, &mBufferSizeFrames,
&propertySize);
propertySize = sizeof(safetyOffset);
safetyOffset = 0;
err = AudioUnitGetProperty(mOutputUnit, kAudioDevicePropertySafetyOffset,
kAudioUnitScope_Global, 0, &safetyOffset,
&propertySize);
asbd.mFormatID = 0x6c70636d; // 'lpcm'
asbd.mFormatFlags = (kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagIsBigEndian |
kAudioFormatFlagIsPacked);
asbd.mChannelsPerFrame = mNumChannels;
asbd.mSampleRate = mSampleRate;
if(asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) {
asbd.mBitsPerChannel = mBitsPerSample;
} else if(asbd.mFormatFlags & kAudioFormatFlagIsFloat) {
asbd.mBitsPerChannel = 32;
} else {
asbd.mBitsPerChannel = 0;
}
asbd.mFramesPerPacket = 1;
asbd.mBytesPerFrame = (asbd.mBitsPerChannel / 8) * asbd.mChannelsPerFrame;
asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket;
asbd.mReserved = 0;
mBytesPerFrame = asbd.mBytesPerFrame;
if((mBytesPerFrame & (mBytesPerFrame - 1)) != 0) {
printf("Audio buffer size must be a power of two!\n");
return -1;
}
propertySize = sizeof(asbd);
err = AudioUnitSetProperty(mOutputUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &asbd, propertySize);
checkErr(err);
if(mAudioBuffer != NULL) {
delete mAudioBuffer;
mAudioBufferSize = 0;
}
mAudioBufferSize = mBytesPerFrame * mBufferSizeFrames * 2;
mAudioBuffer = new UInt8[mAudioBufferSize];
bzero(mAudioBuffer, mAudioBufferSize);
return err;
}
#pragma mark -
#pragma mark -- IO Procs --
OSStatus AudioBackEnd::OutputProc(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *TimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData) {
OSStatus err = noErr;
AudioBackEnd *This = (AudioBackEnd *)inRefCon;
UInt8 *dstPtr;
UInt32 bytesToCopy;
UInt32 bytesUntilEnd;
This->mFramesProcessed += inNumberFrames;
dstPtr = (UInt8 *)ioData->mBuffers[0].mData;
if(This->mAudioBuffer == NULL) {
bzero(dstPtr, inNumberFrames * This->mBytesPerFrame);
return noErr;
}
bytesToCopy = inNumberFrames * This->mBytesPerFrame;
bytesUntilEnd = This->mAudioBufferSize - This->mAudioBufferReadIndex;
if(bytesUntilEnd < bytesToCopy) {
memcpy(dstPtr, &This->mAudioBuffer[This->mAudioBufferReadIndex],
bytesUntilEnd);
memcpy(dstPtr, This->mAudioBuffer, bytesToCopy - bytesUntilEnd);
This->mAudioBufferReadIndex = bytesToCopy - bytesUntilEnd;
} else {
memcpy(dstPtr, &This->mAudioBuffer[This->mAudioBufferReadIndex],
bytesToCopy);
This->mAudioBufferReadIndex += bytesToCopy;
}
while(This->mFramesProcessed >= This->mBufferSizeFrames) {
This->mFramesProcessed -= This->mBufferSizeFrames;
if(This->mCallback != NULL) {
This->mCallback(This->mCallbackArg);
}
}
return err;
}
void AudioBackEnd::setCallback(playthruCallback func, void *arg) {
mCallback = func;
mCallbackArg = arg;
}
UInt32 AudioBackEnd::BufferSizeFrames() {
return mBufferSizeFrames;
}
int AudioBackEnd::sendAudioBuffer(void *buffer, int numFrames) {
UInt8 *dstBuffer;
int totalBytes;
mAudioBufferWriteIndex += (mAudioBufferSize / 2);
mAudioBufferWriteIndex &= (mAudioBufferSize - 1);
dstBuffer = &mAudioBuffer[mAudioBufferWriteIndex];
totalBytes = mBytesPerFrame * numFrames;
memcpy(dstBuffer, buffer, totalBytes);
dstBuffer += totalBytes;
bzero(dstBuffer, (mBufferSizeFrames * mBytesPerFrame) - totalBytes);
return numFrames;
}

View File

@ -1,86 +0,0 @@
/*
*
* This is based on Apple example software AudioBackEnd.cpp
*
* Copyright © 2004 Apple Computer, Inc., All Rights Reserved
* Original Apple code modified by Daniel Sumorok
*
* 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 __AudioBackEnd_H__
#define __AudioBackEnd_H__
#define checkErr( err) \
if(err) {\
OSStatus error = static_cast<OSStatus>(err);\
fprintf(stderr, "AudioBackEnd Error: %ld -> %s: %d\n", error,\
__FILE__, \
__LINE__\
);\
fflush(stdout);\
}
#include <CoreAudio/CoreAudio.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioUnit/AudioUnit.h>
#include <pthread.h>
#include "AudioDevice.h"
typedef void (*playthruCallback)(void *arg);
class AudioBackEnd {
public:
AudioBackEnd(int bitsPerSample, int numChannels, int sampleRate);
~AudioBackEnd();
OSStatus Init();
OSStatus Start();
OSStatus Stop();
Boolean IsRunning();
void setCallback(playthruCallback func, void *arg);
UInt32 BufferSizeFrames();
int sendAudioBuffer(void *buffer, int numFrames);
private:
OSStatus SetupGraph();
OSStatus CallbackSetup();
OSStatus SetupBuffers();
static OSStatus OutputProc(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData);
AudioDevice mOutputDevice;
AUGraph mGraph;
AUNode mOutputNode;
AudioUnit mOutputUnit;
int mBitsPerSample;
int mSampleRate;
int mNumChannels;
playthruCallback mCallback;
void *mCallbackArg;
UInt32 mBufferSizeFrames;
UInt32 mFramesProcessed;
UInt8 *mAudioBuffer;
UInt32 mAudioBufferWriteIndex;
UInt32 mAudioBufferReadIndex;
UInt32 mBytesPerFrame;
UInt32 mAudioBufferSize;
};
#endif //__AudioBackEnd_H__

View File

@ -1,97 +0,0 @@
/* Copyright: © Copyright 2004 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
AudioDevice.cpp
=============================================================================*/
#include "AudioDevice.h"
void AudioDevice::Init(AudioDeviceID devid, bool isInput)
{
mID = devid;
mIsInput = isInput;
if (mID == kAudioDeviceUnknown) return;
UInt32 propsize;
propsize = sizeof(UInt32);
verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertySafetyOffset, &propsize, &mSafetyOffset));
propsize = sizeof(UInt32);
verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyBufferFrameSize, &propsize, &mBufferSizeFrames));
propsize = sizeof(AudioStreamBasicDescription);
verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyStreamFormat, &propsize, &mFormat));
}
void AudioDevice::SetBufferSize(UInt32 size)
{
UInt32 propsize = sizeof(UInt32);
verify_noerr(AudioDeviceSetProperty(mID, NULL, 0, mIsInput, kAudioDevicePropertyBufferFrameSize, propsize, &size));
propsize = sizeof(UInt32);
verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyBufferFrameSize, &propsize, &mBufferSizeFrames));
}
int AudioDevice::CountChannels()
{
OSStatus err;
UInt32 propSize;
int result = 0;
err = AudioDeviceGetPropertyInfo(mID, 0, mIsInput, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
if (err) return 0;
AudioBufferList *buflist = (AudioBufferList *)malloc(propSize);
err = AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyStreamConfiguration, &propSize, buflist);
if (!err) {
for (UInt32 i = 0; i < buflist->mNumberBuffers; ++i) {
result += buflist->mBuffers[i].mNumberChannels;
}
}
free(buflist);
return result;
}
char * AudioDevice::GetName(char *buf, UInt32 maxlen)
{
verify_noerr(AudioDeviceGetProperty(mID, 0, mIsInput, kAudioDevicePropertyDeviceName, &maxlen, buf));
return buf;
}

View File

@ -1,72 +0,0 @@
/* Copyright: © Copyright 2004 Apple Computer, Inc. All rights reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
AudioDevice.h
=============================================================================*/
#ifndef __AudioDevice_h__
#define __AudioDevice_h__
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
class AudioDevice {
public:
AudioDevice() : mID(kAudioDeviceUnknown) { }
AudioDevice(AudioDeviceID devid, bool isInput) { Init(devid, isInput); }
void Init(AudioDeviceID devid, bool isInput);
bool Valid() { return mID != kAudioDeviceUnknown; }
void SetBufferSize(UInt32 size);
int CountChannels();
char * GetName(char *buf, UInt32 maxlen);
public:
AudioDeviceID mID;
bool mIsInput;
UInt32 mSafetyOffset;
UInt32 mBufferSizeFrames;
AudioStreamBasicDescription mFormat;
};
#endif // __AudioDevice_h__

View File

@ -1,59 +0,0 @@
/*
* Controller.h - Simple application window management.
*
* $Id$
*
* 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
*/
#import <Cocoa/Cocoa.h>
#import "PrefsEditor.h"
// If the application supports multiple windows,
// ENABLE_MULTIPLE can be defined in config.h
@interface Controller : NSApplication
{
#ifdef ENABLE_MULTIPLE
NSMutableArray *emulators; // Array of created Emulators
#endif
IBOutlet Emulator *theEmulator;
IBOutlet PrefsEditor *thePrefsEditor;
}
- (void) dispatchKeyEvent: (NSEvent *)event
type: (NSEventType)type;
- (void) dispatchEvent: (NSEvent *)event
type: (NSEventType)type;
- (IBAction) HelpHowTo: (id)sender;
- (IBAction) HelpToDo: (id)sender;
- (IBAction) HelpVersions: (id)sender;
#ifdef ENABLE_MULTIPLE
- (IBAction) NewEmulator: (id)sender;
- (IBAction) PauseAll: (id)sender;
- (IBAction) RunAll: (id)sender;
- (IBAction) TerminateAll: (id)sender;
#endif
- (BOOL) isAnyEmulatorDisplayingSheets;
- (BOOL) isAnyEmulatorRunning;
- (short) emulatorCreatedCount; // If any emulator environments have been setup, count how many
@end

View File

@ -1,410 +0,0 @@
/*
* Controller.m - Simple application window management.
*
* $Id$
*
* 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
*/
#import "Controller.h"
#import "Emulator.h"
#import "sysdeps.h" // Types used in Basilisk C++ code
#import <main.h>
#import <prefs.h>
#define DEBUG 0
#import <debug.h>
#import "misc_macosx.h"
#import "video_macosx.h"
@implementation Controller
//
// Standard NSApplication methods that we override
//
- (id) init
{
#ifdef ENABLE_MULTIPLE
emulators = [NSMutableArray new];
#endif
return [super init];
}
- (void) dealloc
{
#ifdef ENABLE_MULTIPLE
[emulators dealloc];
#endif
[super dealloc];
}
- (void) awakeFromNib
{
#ifdef ENABLE_MULTIPLE
[self NewEmulator: self]; // So the user gets something on screen
#endif
[[NSApplication sharedApplication]
setDelegate: self]; // Enable applicationShouldTerminate
}
- (void) sendEvent: (NSEvent *)event;
{
// We can either process the event ourselves,
// or pass it to our superclass for the other UI objects to process
bool passToSuper = false;
if ( [self isAnyEmulatorDisplayingSheets] ||
[[thePrefsEditor window] isVisible] || ! [self isAnyEmulatorRunning] )
passToSuper = true;
if ( [[theEmulator screen] isFullScreen] )
passToSuper = false;
if ( passToSuper )
[super sendEvent: event]; // NSApplication default
else
{
NSEventType type = [event type];
if ( type == NSKeyUp || type == NSKeyDown || type == NSFlagsChanged )
[self dispatchKeyEvent: event
type: type];
else
[self dispatchEvent: event
type: type];
}
}
// NSApplication methods which are invoked through delegation
- (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *)app
{ return YES; }
- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *)app
{
short count;
const char *stillRunningMessage;
if ( [thePrefsEditor hasEdited] )
if ( ChoiceAlert("Preferences have been edited",
"Save changes", "Quit") )
SavePrefs();
// if ( edited )
// {
// NSString *title = [NSString stringWithCString: getString(STR_WARNING_ALERT_TITLE)],
// *msg = @"Preferences have been edited",
// *def = @"Save changes",
// *alt = @"Quit Application",
// *other = @"Continue";
//
// switch ( NSRunAlertPanel(title, msg, def, alt, other, nil) )
// {
// case NSAlertDefault: savePrefs();
// case NSAlertAlternate: return NSTerminateNow;
// case NSAlertOther: return NSTerminateCancel;
// }
// }
if ( [[thePrefsEditor window] isVisible] )
[[thePrefsEditor window] performClose: self];
count = [self emulatorCreatedCount];
if ( count > 0 )
{
if ( count > 1 )
stillRunningMessage = "Emulators are still running\nExiting Basilisk may lose data";
else
stillRunningMessage = "Emulator is still running\nExiting Basilisk may lose data";
if ( ! ChoiceAlert(stillRunningMessage, "Exit", "Continue") )
return NSTerminateCancel; // NSTerminateLater?
}
return NSTerminateNow;
}
// Event dispatching, called by sendEvent
- (void) dispatchKeyEvent: (NSEvent *)event
type: (NSEventType)type
{
EmulatorView *view;
#ifdef ENABLE_MULTIPLE
// We need to work out what window's Emulator should receive these messages
int tmp;
for ( tmp = 0; tmp < [emulators count], ++tmp )
{
theEmulator = [emulators objectAtIndex: tmp];
view = [theEmulator screen];
if ( [ theEmulator isRunning ] &&
( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
break;
}
if ( tmp < [emulators count] ) // i.e. if we exited the for loop
#else
view = [theEmulator screen];
if ( [theEmulator isRunning] &&
( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
#endif
{
D(NSLog(@"Got a key event - %d\n", [event keyCode]));
switch ( type )
{
case NSKeyUp:
[view keyUp: event];
break;
case NSKeyDown:
D(NSLog(@"%s - NSKeyDown - %@", __PRETTY_FUNCTION__, event));
[view keyDown: event];
break;
case NSFlagsChanged:
[view flagsChanged: event];
break;
default:
NSLog(@"%s - Sent a non-key event (logic error)",
__PRETTY_FUNCTION__);
[super sendEvent: event];
}
}
else // No Basilisk window is key (maybe a panel or pane).
[super sendEvent: event]; // Call NSApplication default
}
- (void) dispatchEvent: (NSEvent *)event
type: (NSEventType)type
{
EmulatorView *view;
BOOL fullScreen;
#ifdef ENABLE_MULTIPLE
// We need to work out what window's Emulator should receive these messages
int tmp;
for ( tmp = 0; tmp < [emulators count], ++tmp )
{
theEmulator = [emulators objectAtIndex: tmp];
view = [theEmulator screen];
fullScreen = [view isFullScreen];
if ( [theEmulator isRunning] &&
( fullScreen || [[theEmulator window] isMainWindow] ) )
break;
}
if ( tmp < [emulators count] ) // i.e. if we exited the for loop
#else
view = [theEmulator screen];
fullScreen = [view isFullScreen];
if ( [theEmulator isRunning] &&
( fullScreen || [[theEmulator window] isMainWindow] ) )
#endif
{
if ( fullScreen || [view mouseInView: event] )
{
switch ( type )
{
case NSLeftMouseDown:
[view mouseDown: event];
break;
case NSLeftMouseUp:
[view mouseUp: event];
break;
case NSLeftMouseDragged:
case NSMouseMoved:
if ( fullScreen )
[view fullscreenMouseMove];
else
[view processMouseMove: event];
break;
default:
[super sendEvent: event]; // NSApplication default
}
return;
}
}
// Either the pointer is not in the Emulator's screen, no Basilisk window is running,
// or no Basilisk window is main (e.g. there might be a panel or pane up).
//
// We should just be calling NSApp's default sendEvent, but then for some reason
// mouseMoved events are still passed to our EmulatorView, so we filter them out.
if ( type != NSMouseMoved )
[super sendEvent: event];
}
// Methods to display documentation:
- (IBAction) HelpHowTo: (id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource: @"HowTo"
ofType: @"html"];
if ( ! path )
InfoSheet(@"Cannot find HowTo.html", [theEmulator window]);
else
if ( ! [[NSWorkspace sharedWorkspace] openFile: path] )
InfoSheet(@"Cannot open HowTo.html with default app", [theEmulator window]);
}
- (IBAction) HelpToDo: (id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource: @"ToDo"
ofType: @"html"];
if ( ! path )
InfoSheet(@"Cannot find ToDo.html", [theEmulator window]);
else
if ( ! [[NSWorkspace sharedWorkspace] openFile: path
withApplication: @"TextEdit"] )
InfoSheet(@"Cannot open ToDo.html with TextEdit", [theEmulator window]);
}
- (IBAction) HelpVersions: (id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource: @"Versions"
ofType: @"html"];
if ( ! path )
InfoSheet(@"Cannot find Versions.html", [theEmulator window]);
else
if ( ! [[NSWorkspace sharedWorkspace] openFile: path
withApplication: @"TextEdit"] )
InfoSheet(@"Cannot open Versions.html with TextEdit",
[theEmulator window]);
}
// Menu items which for managing more than one window
#ifdef ENABLE_MULTIPLE
- (IBAction) NewEmulator: (id)sender
{
NSString *title;
if ( ! [NSBundle loadNibNamed:@"Win512x342" owner:self] )
{
NSLog(@"%s - LoadNibNamed@Win512x342 failed", __PRETTY_FUNCTION__);
return;
}
if ( theEmulator == nil)
{
NSLog(@"%s - Newly created emulator's NIB stuff not fully linked?", __PRETTY_FUNCTION__);
return;
}
[emulators addObject: theEmulator];
title = [NSString localizedStringWithFormat:@"BasiliskII Emulator %d", [emulators count]];
[theEmulator -> win setTitle: title];
}
- (IBAction) PauseAll: (id)sender
{
[emulators makeObjectsPerformSelector:@selector(Suspend:)
withObject:self];
}
- (IBAction) RunAll: (id)sender
{
[emulators makeObjectsPerformSelector:@selector(Resume:)
withObject:self];
}
- (IBAction) TerminateAll: (id)sender
{
[emulators makeObjectsPerformSelector:@selector(Terminate:)
withObject:self];
}
#endif
- (BOOL) isAnyEmulatorDisplayingSheets
{
#ifdef ENABLE_MULTIPLE
int tmp;
for ( tmp = 0; tmp < [emulators count], ++tmp )
if ( [[[emulators objectAtIndex: tmp] window] attachedSheet] )
break;
if ( tmp < [emulators count] ) // i.e. if we exited the for loop
#else
if ( [[theEmulator window] attachedSheet] )
#endif
return TRUE;
return FALSE;
}
- (BOOL) isAnyEmulatorRunning
{
#ifdef ENABLE_MULTIPLE
int tmp;
for ( tmp = 0; tmp < [emulators count], ++tmp )
if ( [[emulators objectAtIndex: tmp] isRunning] )
break;
if ( tmp < [emulators count] ) // i.e. if we exited the for loop
#else
if ( [theEmulator isRunning] )
#endif
return TRUE;
return FALSE;
}
- (short) emulatorCreatedCount
{
short count = 0;
#ifdef ENABLE_MULTIPLE
int tmp;
for ( tmp = 0; tmp < [emulators count], ++tmp )
if ( [[emulators objectAtIndex: tmp] uaeCreated] )
++count;
#else
if ( [theEmulator uaeCreated] )
++count;
#endif
return count;
}
@end

View File

@ -1,11 +0,0 @@
Basilisk II is an open source, 68k Mac. emulator.
<BR>
It enables you to run 68k MacOS software on your computer, even if you are using a different operating system (however, you do need a copy of the MacOS and a Macintosh ROM image to use it).
<CENTER>
<A HREF="http://basilisk.cebix.net">The Official Basilisk II Home Page</A>
</CENTER>
<RIGHT>
MacOS X (native windowing) port
<BR>
by Nigel Pearson &lt;nigel@ind.tansu.com.au&gt;
</RIGHT>

View File

@ -1,82 +0,0 @@
/*
* Emulator.h - Class whose actions are attached GUI widgets in a window,
* used to control a single Basilisk II emulated Macintosh.
*
* $Id$
*
* 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
*/
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import "EmulatorView.h"
#import "NNThread.h"
@interface Emulator : NSObject
{
NNThread *emul; // Run emulThread
NNTimer *RTC, // Invoke RTCinterrupt
*redraw, // Invoke redrawScreen
*tick, // Invoke tickInterrupt
*xPRAM; // Invoke xPRAMbackup
BOOL uaeCreated, // Has thread created the emulator environment?
running; // Is the emulator currently grinding away?
float redrawDelay; // Seconds until next screen update
// UI elements that this class changes the state of
IBOutlet NSProgressIndicator *barberPole;
IBOutlet NSButton *runOrPause;
IBOutlet EmulatorView *screen;
IBOutlet NSSlider *speed;
IBOutlet NSWindow *win;
}
// The following allow the Controller and PrefsEditor classes to access our internal data
- (BOOL) isRunning;
- (BOOL) uaeCreated;
- (EmulatorView *) screen;
- (NSSlider *) speed;
- (NSWindow *) window;
- (void) runUpdate; // Update some UI elements
- (IBAction) Benchmark: (id)sender;
- (IBAction) Interrupt: (id)sender;
- (IBAction) PowerKey: (id)sender;
- (IBAction) Restart: (id)sender;
- (IBAction) Resume: (id)sender;
- (IBAction) ScreenHideShow:(NSButton *)sender;
- (IBAction) Snapshot: (id)sender;
- (IBAction) SpeedChange: (NSSlider *)sender;
- (IBAction) Suspend: (id)sender;
- (IBAction) Terminate: (id)sender;
- (IBAction) ToggleState: (NSButton *)sender;
- (IBAction) ZapPRAM: (id)sender;
- (void) createThreads;
- (void) exitThreads;
- (void) emulThread; // Thread for processor emulator
- (void) RTCinterrupt; // Emulator real time clock update
- (void) redrawScreen; // Draw emulator screen in window
- (void) tickInterrupt; // Draw emulator screen in window
- (void) xPRAMbackup; // PRAM watchdog
@end

View File

@ -1,473 +0,0 @@
/*
* Emulator.mm - Class whose actions are attached to GUI widgets in a window,
* used to control a single Basilisk II emulated Macintosh.
*
* $Id$
*
* 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
*/
#import "Emulator.h"
#import "EmulatorView.h"
#import "sysdeps.h" // Types used in Basilisk C++ code
#import "main_macosx.h" // Prototypes for QuitEmuNoExit() and InitEmulator()
#import "misc_macosx.h" // Some other prototypes
#import "video_macosx.h" // Some window/view globals
#import "adb.h"
#import "main.h"
#import "prefs.h"
#import "timer.h"
#undef check // memory.h defines a check macro,
// which may clash with an OS X one on 10.1 or 10.2
#import "cpu_emulation.h"
#define DEBUG 0
#import "debug.h"
@implementation Emulator
// NSWindow method, which is invoked via delegation
- (BOOL) windowShouldClose: (id)sender
{
if ( uaeCreated )
{
NSLog(@"windowShouldClose returning NO");
return NO; // Should initiate poweroff and return NSTerminateLater ?
}
NSLog(@"windowShouldClose returning YES");
return YES;
}
// Default methods
- (Emulator *) init
{
int frameSkip;
self = [super init];
running = NO; // Save churn when application loads
// running = YES;
uaeCreated = NO;
frameSkip = PrefsFindInt32("frameskip");
if ( frameSkip )
redrawDelay = frameSkip / 60.0;
else
redrawDelay = 0.0;
// We do this so that we can work out if we are in full screen mode:
parse_screen_prefs(PrefsFindString("screen"));
[self createThreads];
return self;
}
- (void) awakeFromNib
{
the_win = win; // Set global for access by Basilisk C++ code
[win setDelegate: self]; // Enable windowShouldClose calling
// Try to speed up everything
//[win setHasShadow: NO]; // This causes view & window to now be drawn correctly
[win useOptimizedDrawing: YES];
[win makeKeyAndOrderFront:self];
if ( redrawDelay )
[speed setFloatValue: 1.0 / redrawDelay];
else
[speed setFloatValue: 60.0];
if ( runOrPause == nil )
NSLog(@"%s - runOrPause button pointer is nil!", __PRETTY_FUNCTION__);
[self runUpdate];
}
// Helpers which other classes use to access our private stuff
- (BOOL) isRunning { return running; }
- (BOOL) uaeCreated { return uaeCreated; }
- (EmulatorView *) screen { return screen; }
- (NSSlider *) speed { return speed; }
- (NSWindow *) window { return win; }
// Update some UI elements
- (void) runUpdate
{
if ( running )
[runOrPause setState: NSOnState]; // Running. Change button label to 'Pause'
else
[runOrPause setState: NSOffState]; // Paused. Change button label to 'Run'
[win setDocumentEdited: uaeCreated]; // Set the little dimple in the close button
}
// Methods invoked by buttons & menu items
- (IBAction) Benchmark: (id)sender;
{
BOOL wasRunning = running;
if ( running )
[self Suspend: self];
[screen benchmark];
if ( wasRunning )
[self Resume: self];
}
#ifdef NIGEL
- (IBAction) EjectCD: (id)sender;
{
NSString *path;
const char *cdrom = PrefsFindString("cdrom");
if ( cdrom )
{
#include <sys/param.h>
#define KERNEL
#include <sys/mount.h>
struct statfs buf;
if ( fsstat(path, &buf) < 0 )
return;
path = [NSString stringWithCString: cdrom];
[[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: path];
// [path release];
}
}
#endif
- (IBAction) Interrupt: (id)sender;
{
WarningSheet (@"Interrupt action not yet supported", win);
}
- (IBAction) PowerKey: (id)sender;
{
if ( uaeCreated ) // If Mac has started
{
ADBKeyDown(0x7f); // Send power key, which is also
ADBKeyUp(0x7f); // called ADB_RESET or ADB_POWER
}
else
{
running = YES; // Start emulator
[self runUpdate];
[self Resume: nil];
}
}
- (IBAction) Restart: (id)sender
{
if ( ! running )
{
running = YES; // Start emulator
[self runUpdate];
[self Resume: nil];
}
if ( running )
#ifdef UAE_CPU_HAS_RESET
reset680x0();
#else
{
uaeCreated = NO;
[redraw suspend];
NSLog (@"%s - uae_cpu reset not yet supported, will try to fake it",
__PRETTY_FUNCTION__);
[screen clear];
[screen display];
[emul terminate]; QuitEmuNoExit();
// OK. We have killed & cleaned up. Now, start afresh:
#include <sys.h>
int argc = 0;
char **argv;
PrefsInit(NULL, argc, argv);
SysInit();
emul = [NNThread new];
[emul perform:@selector(emulThread) of:self];
[emul start];
if ( display_type != DISPLAY_SCREEN )
[redraw resume];
}
#endif
}
- (IBAction) Resume: (id)sender
{
[RTC resume];
[emul resume];
if ( display_type != DISPLAY_SCREEN )
[redraw resume];
[tick resume];
[xPRAM resume];
}
- (IBAction) ScreenHideShow: (NSButton *)sender;
{
WarningSheet(@"Nigel doesn't know how to shrink or grow this window",
@"Maybe you can grab the source code and have a go yourself?",
nil, win);
}
- (IBAction) Snapshot: (id) sender
{
if ( screen == nil || uaeCreated == NO )
WarningSheet(@"The emulator has not yet started.",
@"There is no screen output to snapshot",
nil, win);
else
{
NSData *TIFFdata;
[self Suspend: self];
TIFFdata = [screen TIFFrep];
if ( TIFFdata == nil )
NSLog(@"%s - Unable to convert Basilisk screen to a TIFF representation",
__PRETTY_FUNCTION__);
else
{
NSSavePanel *sp = [NSSavePanel savePanel];
[sp setRequiredFileType:@"tiff"];
if ( [sp runModalForDirectory:NSHomeDirectory()
file:@"B2-screen-snapshot.tiff"] == NSOKButton )
if ( ! [TIFFdata writeToFile:[sp filename] atomically:YES] )
NSLog(@"%s - Could not write TIFF data to file @%",
__PRETTY_FUNCTION__, [sp filename]);
}
if ( running )
[self Resume: self];
}
}
- (IBAction) SpeedChange: (NSSlider *)sender
{
float frequency = [sender floatValue];
[redraw suspend];
if ( frequency == 0.0 )
redrawDelay = 0.0;
else
{
frequencyToTickDelay(frequency);
redrawDelay = 1.0 / frequency;
[redraw changeIntervalTo: (int)(redrawDelay * 1e6)
units: NNmicroSeconds];
if ( running && display_type != DISPLAY_SCREEN )
[redraw resume];
}
}
- (IBAction) Suspend: (id)sender
{
[RTC suspend];
[emul suspend];
[redraw suspend];
[tick suspend];
[xPRAM suspend];
}
- (IBAction) ToggleState: (NSButton *)sender
{
running = [sender state]; // State of the toggled NSButton
if ( running )
[self Resume: nil];
else
[self Suspend: nil];
}
- (IBAction) Terminate: (id)sender;
{
[self exitThreads];
[win performClose: self];
}
#include <xpram.h>
#define XPRAM_SIZE 256
uint8 lastXPRAM[XPRAM_SIZE]; // Copy of PRAM
- (IBAction) ZapPRAM: (id)sender;
{
memset(XPRAM, 0, XPRAM_SIZE);
memset(lastXPRAM, 0, XPRAM_SIZE);
ZapPRAM();
}
//
// Threads, Timers and stuff to manage them:
//
- (void) createThreads
{
#ifdef USE_PTHREADS
// Make UI threadsafe:
[NSThread detachNewThreadSelector:(SEL)"" toTarget:nil withObject:nil];
//emul = [[NNThread alloc] initWithAutoReleasePool];
#endif
emul = [NNThread new];
RTC = [NNTimer new];
redraw = [[NNTimer alloc] initWithAutoRelPool];
tick = [NNTimer new];
xPRAM = [NNTimer new];
[emul perform:@selector(emulThread) of:self];
[RTC repeat:@selector(RTCinterrupt) of:self
every:1
units:NNseconds];
[redraw repeat:@selector(redrawScreen) of:self
every:(int)(1000*redrawDelay)
units:NNmilliSeconds];
[tick repeat:@selector(tickInterrupt) of:self
every:16625
units:NNmicroSeconds];
[xPRAM repeat:@selector(xPRAMbackup) of:self
every:60
units:NNseconds];
if ( running ) // Start emulator, then threads in most economical order
{
[emul start];
[xPRAM start];
[RTC start];
if ( display_type != DISPLAY_SCREEN )
[redraw start];
[tick start];
}
}
- (void) exitThreads
{
running = NO;
[emul terminate]; [emul release]; emul = nil;
[tick invalidate]; [tick release]; tick = nil;
[redraw invalidate]; [redraw release]; redraw = nil;
[RTC invalidate]; [RTC release]; RTC = nil;
[xPRAM invalidate]; [xPRAM release]; xPRAM = nil;
}
- (void) emulThread
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
if ( ! InitEmulator() )
{
[redraw suspend]; // Stop the barberpole
ErrorSheet(@"Cannot start Emulator", @"", @"Quit", win);
}
else
{
memcpy(lastXPRAM, XPRAM, XPRAM_SIZE);
uaeCreated = YES; // Enable timers to access emulated Mac's memory
while ( screen == nil ) // If we are still loading from Nib?
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow: 1.0]];
[self runUpdate]; // Set the window close gadget to dimpled
Start680x0(); // Start 68k and jump to ROM boot routine
puts ("Emulator exited normally");
}
[pool release];
QuitEmulator();
}
- (void) RTCinterrupt
{
if ( ! uaeCreated )
return;
WriteMacInt32 (0x20c, TimerDateTime() ); // Update MacOS time
SetInterruptFlag(INTFLAG_1HZ);
TriggerInterrupt();
}
- (void) redrawScreen
{
if ( display_type == DISPLAY_SCREEN )
{
NSLog(@"We are in fullscreen mode - why was redrawScreen() called?");
return;
}
[barberPole animate:self]; // wobble the pole
[screen setNeedsDisplay: YES]; // redisplay next time through runLoop
// Or, use a direct method. e.g.
// [screen display] or [screen cgDrawInto: ...];
}
#include <main.h> // For #define INTFLAG_60HZ
#include <rom_patches.h> // For ROMVersion
#include "macos_util_macosx.h" // For HasMacStarted()
- (void) tickInterrupt
{
if ( ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted() )
{
SetInterruptFlag (INTFLAG_60HZ);
TriggerInterrupt ();
}
}
- (void) xPRAMbackup
{
if ( uaeCreated &&
memcmp(lastXPRAM, XPRAM, XPRAM_SIZE) ) // if PRAM changed from copy
{
memcpy (lastXPRAM, XPRAM, XPRAM_SIZE); // re-copy
SaveXPRAM (); // and save to disk
}
}
@end

View File

@ -1,108 +0,0 @@
/*
* EmulatorView.h - Custom NSView for Basilisk II window input & output
*
* $Id$
*
* 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
*/
#ifdef NSBITMAP
#import <AppKit/NSBitmapImageRep.h>
#endif
#import <AppKit/NSView.h>
@interface EmulatorView : NSView
{
#ifdef CGIMAGEREF
CGImageRef cgImgRep;
#endif
#ifdef NSBITMAP
NSBitmapImageRep *bitmap;
#else
void *bitmap;
#endif
#ifdef CGDRAWBITMAP
short bps, spp, bpp;
int bytesPerRow;
BOOL isPlanar, hasAlpha;
#endif
float numBytes;
short x, y;
BOOL drawView, // Set when the bitmap is all set up
// and ready to display
fullScreen; // Is this Emulator using the whole screen?
NSRect displayBox; // Cached dimensions of the screen
int screen_height; // Height of the screen with the key window
}
- (void) benchmark;
- (NSData *) TIFFrep; // Used for snapshot function
// Enable display of, and drawing into, the view
#ifdef NSBITMAP
- (void) readyToDraw: (NSBitmapImageRep *) theBitmap
imageWidth: (short) width
imageHeight: (short) height;
#endif
#ifdef CGIMAGEREF
- (void) readyToDraw: (CGImageRef) image
bitmap: (void *) theBitmap
imageWidth: (short) width
imageHeight: (short) height;
#endif
#ifdef CGDRAWBITMAP
- (void) readyToDraw: (void *) theBitmap
width: (short) width
height: (short) height
bps: (short) bitsPerSample
spp: (short) samplesPerPixel
bpp: (short) bitsPerPixel
bpr: (int) bpr
isPlanar: (BOOL) planar
hasAlpha: (BOOL) alpha;
#endif
- (void) disableDrawing;
- (void) startedFullScreen: (CGDirectDisplayID) theDisplay;
- (void) blacken;
- (void) clear;
- (short) width;
- (short) height;
- (BOOL) isFullScreen;
- (BOOL) mouseInView: (NSEvent *) event;
- (BOOL) mouseInView;
- (void) fullscreenMouseMove;
- (BOOL) processMouseMove: (NSEvent *) event;
#ifdef CGDRAWBITMAP
- (void) CGDrawBitmap;
#endif
#ifdef CGIMAGEREF
void cgDrawInto(NSRect rect, CGImageRef bitmap);
#endif
@end

View File

@ -1,550 +0,0 @@
/*
* EmulatorView.mm - Custom NSView for Basilisk II windowed graphics output
*
* $Id$
*
* 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
*/
#import "sysdeps.h" // Types used in Basilisk C++ code,
#define DEBUG 0
#import <debug.h>
#import <Cocoa/Cocoa.h>
#import "main_macosx.h" // For WarningAlert() et al prototypes
#import "misc_macosx.h" // For InfoSheet() prototype
#import "video_macosx.h" // For init_* globals, and bitmap drawing strategy
#import "EmulatorView.h"
@implementation EmulatorView
//
// Standard NSView methods that we override
//
- (id) initWithFrame: (NSRect) frameRect
{
self = [super initWithFrame: frameRect];
output = self; // Set global for access by Basilisk C++ code
// bitmap = nil; // Set by readyToDraw:
drawView = NO; // Disable drawing until later
fullScreen = NO;
return self;
}
- (void) awakeFromNib
{
// Here we store the height of the screen which the app was opened on.
// NSApplication's sendEvent: always uses that screen for its mouse co-ords
screen_height = (int) [[NSScreen mainScreen] frame].size.height;
}
// Mouse click in this window. If window is not active,
// should the click be passed to this view?
- (BOOL) acceptsFirstMouse: (NSEvent *) event
{
return [self mouseInView];
}
//
// Key event processing.
// OS X doesn't send us separate events for the modifier keys
// (shift/control/command), so we need to monitor them separately
//
#include <adb.h>
static int prevFlags;
- (void) flagsChanged: (NSEvent *) event
{
int flags = [event modifierFlags];
if ( (flags & NSAlphaShiftKeyMask) != (prevFlags & NSAlphaShiftKeyMask) )
if ( flags & NSAlphaShiftKeyMask )
ADBKeyDown(0x39); // CAPS_LOCK
else
ADBKeyUp(0x39);
if ( (flags & NSShiftKeyMask) != (prevFlags & NSShiftKeyMask) )
if ( flags & NSShiftKeyMask )
ADBKeyDown(0x38); // SHIFT_LEFT
else
ADBKeyUp(0x38);
if ( (flags & NSControlKeyMask) != (prevFlags & NSControlKeyMask) )
if ( flags & NSControlKeyMask )
ADBKeyDown(0x36); // CTL_LEFT
else
ADBKeyUp(0x36);
if ( (flags & NSAlternateKeyMask) != (prevFlags & NSAlternateKeyMask) )
if ( flags & NSAlternateKeyMask )
ADBKeyDown(0x3a); // OPTION_LEFT
else
ADBKeyUp(0x3a);
if ( (flags & NSCommandKeyMask) != (prevFlags & NSCommandKeyMask) )
if ( flags & NSCommandKeyMask )
ADBKeyDown(0x37); // APPLE_LEFT
else
ADBKeyUp(0x37);
prevFlags = flags;
}
//
// Windowed mode. We only send mouse/key events
// if the OS X mouse is within the little screen
//
- (BOOL) mouseInView: (NSEvent *) event
{
NSRect box;
NSPoint loc;
if ( fullScreen )
{
box = displayBox;
loc = [NSEvent mouseLocation];
}
else
{
box = [self frame];
loc = [event locationInWindow];
}
D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f, box.size.width=%f, box.size.height=%f", __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y, box.size.width, box.size.height));
return [self mouse: loc inRect: box];
}
- (BOOL) mouseInView
{
NSPoint loc = [[self window] mouseLocationOutsideOfEventStream];
NSRect box = [self frame];
D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f",
__PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y));
return [self mouse: loc inRect: box];
}
//
// Custom methods
//
- (void) benchmark
{
int i;
float seconds;
NSDate *startDate;
const char *method;
if ( ! drawView )
{
WarningSheet (@"The emulator has not been setup yet.",
@"Try to run, then pause the emulator, first.", nil, [self window]);
return;
}
drawView = NO;
[self lockFocus];
startDate = [NSDate date];
for (i = 1; i < 300; ++i )
#ifdef NSBITMAP
[bitmap draw];
#endif
#ifdef CGIMAGEREF
cgDrawInto([self bounds], cgImgRep);
#endif
#ifdef CGDRAWBITMAP
[self CGDrawBitmap];
#endif
seconds = -[startDate timeIntervalSinceNow];
[self unlockFocus];
drawView = YES;
#ifdef NSBITMAP
method = "NSBITMAP";
#endif
#ifdef CGIMAGEREF
method = "CGIMAGEREF";
#endif
#ifdef CGDRAWBITMAP
method = "CGDRAWBITMAP";
#endif
InfoSheet(@"Ran benchmark (300 screen redraws)",
[NSString stringWithFormat:
@"%.2f seconds, %.3f frames per second (using %s implementation)",
seconds, i/seconds, method],
@"Thanks", [self window]);
}
// Return a TIFF for a snapshot of the screen image
- (NSData *) TIFFrep
{
#ifdef NSBITMAP
return [bitmap TIFFRepresentation];
#else
NSBitmapImageRep *b = [NSBitmapImageRep alloc];
b = [b initWithBitmapDataPlanes: (unsigned char **) &bitmap
pixelsWide: x
pixelsHigh: y
#ifdef CGIMAGEREF
bitsPerSample: CGImageGetBitsPerComponent(cgImgRep)
samplesPerPixel: 3
hasAlpha: NO
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: CGImageGetBytesPerRow(cgImgRep)
bitsPerPixel: CGImageGetBitsPerPixel(cgImgRep)];
#endif
#ifdef CGDRAWBITMAP
bitsPerSample: bps
samplesPerPixel: spp
hasAlpha: hasAlpha
isPlanar: isPlanar
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: bytesPerRow
bitsPerPixel: bpp];
#endif
if ( ! b )
{
ErrorAlert("Could not allocate an NSBitmapImageRep for the TIFF\nTry setting the emulation to millions of colours?");
return nil;
}
return [b TIFFRepresentation];
#endif
}
// Enable display of, and drawing into, the view
#ifdef NSBITMAP
- (void) readyToDraw: (NSBitmapImageRep *) theBitmap
imageWidth: (short) width
imageHeight: (short) height
{
numBytes = [theBitmap bytesPerRow] * height;
#endif
#ifdef CGIMAGEREF
- (void) readyToDraw: (CGImageRef) image
bitmap: (void *) theBitmap
imageWidth: (short) width
imageHeight: (short) height
{
cgImgRep = image;
numBytes = CGImageGetBytesPerRow(image) * height;
#endif
#ifdef CGDRAWBITMAP
- (void) readyToDraw: (void *) theBitmap
width: (short) width
height: (short) height
bps: (short) bitsPerSample
spp: (short) samplesPerPixel
bpp: (short) bitsPerPixel
bpr: (int) bpr
isPlanar: (BOOL) planar
hasAlpha: (BOOL) alpha
{
bps = bitsPerSample;
spp = samplesPerPixel;
bpp = bitsPerPixel;
bytesPerRow = bpr;
isPlanar = planar;
hasAlpha = alpha;
numBytes = bpr * height;
#endif
D(NSLog(@"readyToDraw: theBitmap=%lx\n", theBitmap));
bitmap = theBitmap;
x = width, y = height;
drawView = YES;
[[self window] setAcceptsMouseMovedEvents: YES];
// [[self window] setInitialFirstResponder: self];
[[self window] makeFirstResponder: self];
}
- (void) disableDrawing
{
drawView = NO;
}
- (void) startedFullScreen: (CGDirectDisplayID) display
{
CGRect displayBounds = CGDisplayBounds(display);
fullScreen = YES;
memcpy(&displayBox, &displayBounds, sizeof(displayBox));
}
- (short) width
{
return (short)[self bounds].size.width;
}
- (short) height
{
return (short)[self bounds].size.height;
}
- (BOOL) isFullScreen
{
return fullScreen;
}
- (BOOL) isOpaque
{
return drawView;
}
- (BOOL) processKeyEvent: (NSEvent *) event
{
if ( fullScreen || [self acceptsFirstMouse: event] )
if ( [event isARepeat] )
return NO;
else
return YES;
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
return NO;
}
- (void) keyDown: (NSEvent *) event
{
if ( [self processKeyEvent: event] )
{
int code = [event keyCode];
if ( code == 126 ) code = 0x3e; // CURS_UP
if ( code == 125 ) code = 0x3d; // CURS_DOWN
if ( code == 124 ) code = 0x3c; // CURS_RIGHT
if ( code == 123 ) code = 0x3b; // CURS_LEFT
ADBKeyDown(code);
}
}
- (void) keyUp: (NSEvent *) event
{
if ( [self processKeyEvent: event] )
{
int code = [event keyCode];
if ( code == 126 ) code = 0x3e; // CURS_UP
if ( code == 125 ) code = 0x3d; // CURS_DOWN
if ( code == 124 ) code = 0x3c; // CURS_RIGHT
if ( code == 123 ) code = 0x3b; // CURS_LEFT
ADBKeyUp(code);
}
}
- (void) fullscreenMouseMove
{
NSPoint location = [NSEvent mouseLocation];
D(NSLog (@"%s - loc.x=%f, loc.y=%f",
__PRETTY_FUNCTION__, location.x, location.y));
D(NSLog (@"%s - Sending ADBMouseMoved(%d,%d). (%d-%d)",
__PRETTY_FUNCTION__, (int)location.x,
screen_height - (int)location.y, screen_height, (int)location.y));
ADBMouseMoved((int)location.x, screen_height - (int)location.y);
}
static NSPoint mouse; // Previous/current mouse location
- (BOOL) processMouseMove: (NSEvent *) event
{
if ( ! drawView )
{
D(NSLog(@"Unable to process event - Emulator has not started yet"));
return NO;
}
if ( fullScreen )
{
[self fullscreenMouseMove];
return YES;
}
NSPoint location = [self convertPoint: [event locationInWindow] fromView:nil];
D(NSLog (@"%s - loc.x=%f, loc.y=%f",
__PRETTY_FUNCTION__, location.x, location.y));
if ( NSEqualPoints(location, mouse) )
return NO;
mouse = location;
int mouseY = y - (int) (y * mouse.y / [self height]);
int mouseX = (int) (x * mouse.x / [self width]);
// If the view was not resizable, then this would be simpler:
// int mouseY = y - (int) mouse.y;
// int mouseX = (int) mouse.x;
ADBMouseMoved(mouseX, mouseY);
return YES;
}
- (void) mouseDown: (NSEvent *) event
{
[self processMouseMove: event];
ADBMouseDown(0);
}
- (void) mouseDragged: (NSEvent *) event
{
[self processMouseMove: event];
}
- (void) mouseMoved: (NSEvent *) event
{
#if DEBUG
if ( ! [self mouseInView] )
{
NSLog (@"%s - Received event while outside of view", __PRETTY_FUNCTION__);
return;
}
#endif
[self processMouseMove: event];
}
- (void) mouseUp: (NSEvent *) event
{
[self processMouseMove: event];
ADBMouseUp(0);
}
#if DEBUG
- (void) randomise // Draw some coloured snow in the bitmap
{
unsigned char *data,
*pixel;
#ifdef NSBITMAP
data = [bitmap bitmapData];
#else
data = bitmap;
#endif
for ( int i = 0; i < 1000; ++i )
{
pixel = data + (int) (numBytes * rand() / RAND_MAX);
*pixel = (unsigned char) (256.0 * rand() / RAND_MAX);
}
}
#endif
- (void) drawRect: (NSRect) rect
{
if ( ! drawView ) // If the emulator is still being setup,
return; // we do not want to draw
#if DEBUG
NSLog(@"In drawRect");
[self randomise];
#endif
#ifdef NSBITMAP
NSRectClip(rect);
[bitmap draw];
#endif
#ifdef CGIMAGEREF
cgDrawInto(rect, cgImgRep);
#endif
#ifdef CGDRAWBITMAP
[self CGDrawBitmap];
#endif
}
- (void) setTo: (int) val // Set all of bitmap to val
{
unsigned char *data
#ifdef NSBITMAP
= [bitmap bitmapData];
#else
= (unsigned char *) bitmap;
#endif
memset(data, val, (long unsigned)numBytes);
}
- (void) blacken // Set bitmap black
{
[self setTo: 0];
}
- (void) clear // Set bitmap white
{
[self setTo: 0xFF];
}
//
// Extra drawing stuff
//
#ifdef CGDRAWBITMAP
extern "C" void CGDrawBitmap(...);
- (void) CGDrawBitmap
{
CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext]
graphicsPort];
NSRect rect = [self bounds];
CGRect cgRect = {
{rect.origin.x, rect.origin.y},
{rect.size.width, rect.size.height}
};
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
// CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
CGDrawBitmap(cgContext, cgRect, x, y, bps, spp, bpp,
bytesPerRow, isPlanar, hasAlpha, colourSpace, &bitmap);
}
#endif
#ifdef CGIMAGEREF
void
cgDrawInto(NSRect rect, CGImageRef cgImgRep)
{
CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext]
graphicsPort];
CGRect cgRect = {
{rect.origin.x, rect.origin.y},
{rect.size.width, rect.size.height}
};
// CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
CGContextDrawImage(cgContext, cgRect, cgImgRep);
}
#endif
@end

View File

@ -1,3 +0,0 @@
/* Localized versions of Info.plist keys */
NSHumanReadableCopyright = "Copyright © 1997-2006 Christian Bauer et al. Freely distributable under the terms of the GNU GPL.";

View File

@ -1,131 +0,0 @@
{
IBClasses = (
{
ACTIONS = {
HelpHowTo = id;
HelpToDo = id;
HelpVersions = id;
NewEmulator = id;
PauseAll = id;
RunAll = id;
TerminateAll = id;
};
CLASS = Controller;
LANGUAGE = ObjC;
OUTLETS = {theEmulator = id; thePrefsEditor = id; };
SUPERCLASS = NSApplication;
},
{
ACTIONS = {
Benchmark = id;
Interrupt = id;
PowerKey = id;
Restart = id;
Resume = id;
ScreenHideShow = id;
Snapshot = id;
SpeedChange = id;
Suspend = id;
Terminate = id;
ToggleState = id;
ZapPRAM = id;
};
CLASS = Emulator;
LANGUAGE = ObjC;
OUTLETS = {barberPole = id; runOrPause = id; screen = id; speed = id; win = id; };
SUPERCLASS = NSObject;
},
{CLASS = EmulatorView; LANGUAGE = ObjC; SUPERCLASS = NSView; },
{
ACTIONS = {
Interrupt = id;
PowerKey = id;
Restart = id;
Resume = id;
Snapshot = id;
Suspend = id;
Terminate = id;
ZapPRAM = id;
};
CLASS = FirstResponder;
LANGUAGE = ObjC;
SUPERCLASS = NSObject;
},
{
ACTIONS = {
AddSCSI = id;
AddVolume = id;
BrowseExtFS = id;
BrowsePrefs = id;
BrowseROM = id;
ChangeBootFrom = id;
ChangeCPU = id;
ChangeDisableCD = id;
ChangeDisableSound = id;
ChangeFPU = id;
ChangeKeyboard = id;
ChangeModel = id;
ChangeScreen = id;
CreateVolume = id;
DeleteVolume = id;
EditBytes = id;
EditDelay = id;
EditEtherNetDevice = id;
EditExtFS = id;
EditFrequency = id;
EditMB = id;
EditModemDevice = id;
EditPrinterDevice = id;
EditROMpath = id;
LoadPrefs = id;
RemoveSCSI = id;
RemoveVolume = id;
ResetPrefs = id;
SavePrefs = id;
ShowPrefs = id;
};
CLASS = PrefsEditor;
LANGUAGE = ObjC;
OUTLETS = {
CPU68000 = id;
CPU68020 = id;
CPU68030 = id;
CPU68040 = id;
FPU = id;
IIci = id;
MB = id;
ROMfile = id;
SCSIdisks = id;
bootFromAny = id;
bootFromCD = id;
bytes = id;
classic = id;
delay = id;
depth = id;
disableCD = id;
disableSound = id;
diskImages = id;
emuFreq = id;
emuWin = id;
etherNet = id;
extFS = id;
frequency = id;
height = id;
keyboard = id;
modem = id;
newVolumeSize = id;
newVolumeView = id;
panel = id;
prefsFile = id;
printer = id;
quadra900 = id;
screen = id;
theEmulator = id;
width = id;
window = id;
};
SUPERCLASS = NSObject;
}
);
IBVersion = 1;
}

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>3 11 521 240 0 4 1152 742 </string>
<key>IBEditorPositions</key>
<dict>
<key>29</key>
<string>3 256 365 44 0 0 1152 746 </string>
</dict>
<key>IBFramework Version</key>
<string>349.0</string>
<key>IBLockedObjects</key>
<array>
<integer>288</integer>
</array>
<key>IBOpenObjects</key>
<array>
<integer>29</integer>
<integer>813</integer>
</array>
<key>IBSystem Version</key>
<string>7D24</string>
<key>IBUserGuides</key>
<dict>
<key>VolumeSize</key>
<dict>
<key>guideLocations</key>
<array/>
<key>guidesLocked</key>
<string>NO</string>
</dict>
</dict>
</dict>
</plist>

View File

@ -1,226 +0,0 @@
<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN"><HTML>
<HEAD><TITLE>Basilisk II, Mac OS X port, HowTos</TITLE></HEAD>
<BODY>
<H1> Index </H1>
<UL>
<LI> <A HREF="#minreq"> Minimum Requirements</A> </LI>
<LI> <A HREF="#rom"> Macintosh ROM image</A> </LI>
<LI> <A HREF="#b-disk"> Finding a boot disk</A> </LI>
<LI> <A HREF="#install">Installing the MacOS</A> </LI>
<LI> <A HREF="#mount"> Mounting Unix Files</A> </LI>
<LI> <A HREF="#import"> Importing Mac Files</A> </LI>
<LI> <A HREF="#net"> Networking</A> </LI>
</UL>
<HR>
<H2> <A NAME="minreq"> Minimum Requirements </A> </H2>
To run Basilisk II, you need both:
<UL>
<LI>A Mac ROM image. Even though there is a ROM in your OS X Mac,
it is too new for a 68k Mac to make use of. Any Mac II ROM,
and most of the Quadra ROMS, will work.
<BR> (Quadra 660av and 840av ROMs are currently unusable.
I don't know about Mac LC ROMs. In the near future, Mac Plus,
SE or Classic ROMS may also be usable, though only for emulating
a monochrome Mac). </LI>
<LI>A copy of the MacOS, which at the moment has to either be on
a CD-ROM, or on a disk image </LI>
</UL>
<HR>
<H2> <A NAME="rom"> Macintosh ROM image </A> </H2>
<P> To run Basilisk II, you need a ROM image, which is a data file
containing a copy of the ROM chips from a real 68k Macintosh. </P>
<P> The best way (<I>i.e.</I> most legally acceptable) to get a ROM
image is to produce it from your old Mac. Take a program like CopyROM,
download it onto your old Mac, and use it to produce the image file,
which you then copy or upload to your OS X Mac.
A good page which describes this process is
<A HREF="http://mes.emuunlim.com/tips/capturing_a_mac_rom_image.htm">here</A>.
</P>
<P> The easiest way to get a ROM image is to get one from someone else
(<I>e.g.</I> another Basilisk II user, or an emulation web site).
Note that this probably contravenes several copyright laws. </P>
<P>Once you have your ROM image, you need to tell Basilisk II to use it:
<OL>
<LI> Open the Basilisk II application </LI>
<LI> Go to the 'BasiliskII' menu, then the Preferences...' menu item </LI>
<LI> On the Emulation tab, there is a field 'ROM file:'. Either type in the
path to the ROM file, or click the Browse button and Open the ROM file </LI>
<LI> Click the Save button, so that Basilisk II will be able to find the ROM
each time you boot it </LI>
</OL>
</P>
<P> If you want to test this, press the Run or Power button
(in the top right corner of the 'BasiliskII Emulator' window).
After a few moments you should see a Mac screen, with a picture of a floppy
disk with a flashing question mark. That is the Mac telling you that it needs
a disk to boot from. </P>
<HR>
<H2> <A NAME="b-disk"> Finding a boot disk </A> </H2>
<P> Basilisk II needs a copy of the MacOS to boot from. Anything from System 7
through to MacOS 8.1 should be usable.
<BR> (Felix Eng and I have only tested System 7.0.1, 7.1, 7.5.3 and 7.6,
although Felix also got System 6.0.8 to work with SE/30 Roms) </P>
Basilisk II can currently boot from:
<TABLE BORDER=1>
<TR>
<TD> CD-ROM </TD>
<TD> Most (not all) MacOS Install CDs will also boot your Mac. I also think
that some old Norton Utilities install CDs might have booted 68k Macs </TD>
</TR>
<TR>
<TD> Floppy disk image </TD>
<TD> Jonathan C. Silverstein reports that
<A HREF="http://download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/English-North_American/Macintosh/Utilities/Network_Access_Disk_7.5.sea.bin">this</A> Apple floppy disk image will boot Basilisk II </TD>
</TR>
<TR>
<TD> Preinstalled Basilisk II disk image </TD>
<TD> Another Basilisk II user might be willing to loan you the disk image
that they are using </TD>
</TR>
</TABLE>
<P> It is possible to use Basilisk II with a CD-ROM or floppy image, but
because most bootable CDs have a minimal System Folder, it is better if you
use a disk image with a more complete MacOS installed on it. The next section
tells you how to do this. </P>
<P> Note that there is currently no Install CD image on Apple's Web site, but
they do seem to have MacOS 7.5.3 floppy disk images (all 19 of them). Burning
those images onto a CD (not in the extended format) should allow you to install.
<BR>Thanks to Attilio Farina for this tip! </P>
<H2> <A NAME="install"> Installing the MacOS </A> </H2>
<H3> Create a new BasiliskII disk </H3>
<P> Before you can install the MacOS onto a disk volume,
you need to create a disk to install onto: </P>
<OL>
<LI> Start up the Basilisk application.<BR>
(If it is already running, skip this step)</LI>
<LI> Open the preferences. </LI>
<LI> Go to the Disk Volumes tab. </LI>
<LI> Press the 'Create...' button
(go with the defaults, unless you think you will need a huge disk). </LI>
</OL>
<P> If you want to have more than one hard disk available to Basilisk II,
you could create additional volumes here. </P>
<H3> Installing the MacOS </H3>
<P> Insert your MacOS install CD-ROM, and wait a few moments for the
OS X Finder to mount the disk. While still in your preferences: </P>
<OL>
<LI> Go to the Emulation tab and check that your emulation is appropriate
for your install image
<BR>(<I>e.g.</I> I had to change from Quadra900 to IIci,
because my generic 7.1 install CD didn't support the Quadra),
and that you have the RAM size set appropriately
<BR>(<I>e.g.</I> 8MB RAM may not be enough for a 7.5.3 install). </LI>
<LI> Click the save button. </LI>
<LI> In the BasiliskII Emulator window, click Run. <BR>
(If it is already running, but showing the floppy with the question mark,
press the restart button - the triangle in the bottom right hand corner) <BR>
You should get a HappyMac, and the emulator will start to boot from the CD.
You should then a dialog asking you to format a disk. </LI>
<LI> Click Initialize, then Erase, give the disk an appropriate name
(<I>e.g.</I> Hard Disk), then click OK. </LI>
<LI> Find the OS installer (in my case the CD booted into At Ease, and one of
the first buttons was 'Install System'), and go with the defaults. </LI>
</OL>
<P> After the installer finishes it may try to reboot (or you may need to
force a reboot). When it reboots, BasiliskII may exit. Start it again,
and you should boot into your installed OS. </P>
<HR>
<H2> <A NAME="mount">Mounting Unix Files</A> </H2>
<P> If Basilisk II is running MacOS 7.5.3 or newer, you can easily access some
of the files from your OS X disks. Just set the 'Unix directory to mount' in the
Volumes tab of the Preferences. Next time the Emulator starts up, a new disk
will appear on its Desktop (called Unix). </P>
<P> To prevent clashes with the OS X desktop files, I suggest that the directory
you select is not a whole disk (<I>e.g.</I> '/' or '/Volumes/disk'). Mount a
sub-folder instead (like '/Applications (Mac OS 9)'). </P>
<HR>
<H2> <A NAME="import">Importing Mac Files</A> </H2>
<P> If you are not running MacOS 7.5.3 or newer, the above trick won't work.
This makes getting files into Basilisk II harder. Luckily, Apple's 'Disk Copy'
or 'Disk Utility' can create a disk image file that is compatible
with Basilisk II (<I>i.e.</I> you can add it as a disk volume). </P>
<OL>
<LI> Open 10.1's 'Disk Copy' program, and create a 'Mac Standard' image,
<BR> or 10.3's 'Disk Utility', and create a 'read/write disk image',
<BR> or Disk Copy 6.??? in Classic, and create new image </LI>
<LI> If the image is not mounted, mount it </LI>
<LI> Copy any files that you want to access in the emulator to the mounted
image </LI>
<LI> Unmount the image </LI>
<LI> In Basilisk II's preferences, go to the 'Disk Volumes' tab,
add your new image, and start the emulation </LI>
</OL>
A new disk should appear on the emulation's desktop which contains the files
that you wanted to access. If the emulator complains about a disk needing to
be formatted, you may have chosen the wrong type of image type in 'Disk Copy'
or 'Disk Utility.'
<HR>
<H2> <A NAME="net">Networking</A> </H2>
<P> If your Mac is networked, then your emulated MacOS can also access that
network:
<OL>
<LI> Open Basilisk II, go to the Preferences, then the Hardware tab,
and set the emulator's EtherNet interface to slirp </LI>
<LI> Start the Emulator </LI>
<LI> In the emulated MacOS, open the TCP/IP Control Panel and set:
<UL>
<LI> 'Connect via:' to EtherNet, and </LI>
<LI> 'Configure:' to 'Using DHCP Server' </LI>
</UL>
<LI> Restart the emulation. </LI>
</OL>
You should now be able to surf the web, or FTP download software,
in the emulated Mac. Not sure about AppleTalk networking, though. </P>
<P> Note that this does not require the OS X Mac to be using EtherNet,
any working TCP/IP networking should be fine. I have tested it over
DHCP EtherNet (ADSL modem/router at home), and with a static IP
address at work (which also has an external web proxy/firewall). </P>
<HR>
$Id$
<BR>
Written by Nigel Pearson on 26th March, 2003.
</BODY>
</HTML>

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>BasiliskII</string>
<key>CFBundleGetInfoString</key>
<string>Basilisk II version 1.0, Copyright © 1997-2006 Christian Bauer et al. Mac OS X port 19</string>
<key>CFBundleIconFile</key>
<string>BasiliskII.icns</string>
<key>CFBundleIdentifier</key>
<string></string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>BasiliskII</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>Basilisk II 1.0, Mac OS X port 19</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>NSHelpFile</key>
<string>README.txt</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>Controller</string>
</dict>
</plist>

View File

@ -1,86 +0,0 @@
/*
* MacOSX_sound_if.h
* BasiliskII
*
* Copyright 2006 Daniel Sumorok. All rights reserved.
*
* 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 "AudioBackEnd.h"
#include "MacOSX_sound_if.h"
OSXsoundOutput::OSXsoundOutput() :
player(NULL),
callback(NULL) {
}
void OSXsoundOutput::getMoreSamples(void *arg) {
OSXsoundOutput *me;
me = (OSXsoundOutput *)arg;
if(me == NULL) {
return;
}
if(me->callback == NULL) {
return;
}
me->callback();
}
int OSXsoundOutput::start(int bitsPerSample, int numChannels, int sampleRate) {
stop();
player = new AudioBackEnd(bitsPerSample, numChannels, sampleRate);
if(player != NULL) {
player->setCallback(getMoreSamples, (void *)this);
player->Start();
}
return 0;
}
int OSXsoundOutput::stop() {
if(player != NULL) {
player->Stop();
delete player;
player = NULL;
}
return 0;
}
OSXsoundOutput::~OSXsoundOutput() {
stop();
}
void OSXsoundOutput::setCallback(audioCallback fn) {
callback = fn;
}
unsigned int OSXsoundOutput::bufferSizeFrames() {
if(player != NULL) {
return player->BufferSizeFrames();
}
return 0;
}
int OSXsoundOutput::sendAudioBuffer(void *buffer, int numFrames) {
if(player != NULL) {
return player->sendAudioBuffer(buffer, numFrames);
}
return 0;
}

View File

@ -1,41 +0,0 @@
/*
* MacOSX_sound_if.h
* BasiliskII
*
* Copyright 2006 Daniel Sumorok. All rights reserved.
*
* 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
*/
typedef int (*audioCallback)(void);
class AudioBackEnd;
class OSXsoundOutput {
private:
static void getMoreSamples(void *arg);
AudioBackEnd *player;
audioCallback callback;
public:
OSXsoundOutput();
~OSXsoundOutput();
int start(int bitsPerSample, int numChannels, int sampleRate);
int stop();
int putBuffer(void *buffer, int numSamples);
void setCallback(audioCallback fn);
unsigned int bufferSizeFrames();
int sendAudioBuffer(void *buffer, int numFrames);
};

View File

@ -1,4 +0,0 @@
/* Localized versions of Info.plist keys */
CFBundleName = "BasiliskII";
NSHumanReadableCopyright = "Copyright 1997-2001 Christian Bauer et al., Freely distributable under the terms of the GNU GPL";

View File

@ -1,118 +0,0 @@
{
IBClasses = (
{
ACTIONS = {
NewEmulator = id;
PauseAll = id;
RunAll = id;
ShowAbout = id;
TerminateAll = id;
};
CLASS = Controller;
LANGUAGE = ObjC;
OUTLETS = {myEmulator = id; };
SUPERCLASS = NSObject;
},
{
ACTIONS = {
Interrupt = id;
PowerKey = id;
Restart = id;
Resume = id;
Snapshot = id;
SpeedChange = id;
Suspend = id;
Terminate = id;
ToggleState = id;
ZapPRAM = id;
};
CLASS = Emulator;
LANGUAGE = ObjC;
OUTLETS = {barberPole = id; runOrPause = id; screen = id; speed = id; win = id; };
SUPERCLASS = NSObject;
},
{CLASS = EmulatorView; LANGUAGE = ObjC; SUPERCLASS = NSView; },
{
ACTIONS = {
Interrupt = id;
PowerKey = id;
Restart = id;
Resume = id;
Snapshot = id;
Suspend = id;
Terminate = id;
ZapPRAM = id;
};
CLASS = FirstResponder;
LANGUAGE = ObjC;
SUPERCLASS = NSObject;
},
{
ACTIONS = {
AddSCSI = id;
AddVolume = id;
BrowseEtherNet = id;
BrowseExtFS = id;
BrowseModem = id;
BrowsePrinter = id;
BrowseROM = id;
ChangeBootFrom = id;
ChangeCPU = id;
ChangeDisableCD = id;
ChangeDisableSound = id;
ChangeFPU = id;
ChangeModel = id;
CreateVolume = id;
DeleteVolume = id;
EditBytes = id;
EditDelay = id;
EditDepth = id;
EditEtherNetDevice = id;
EditExtFS = id;
EditFrequency = id;
EditHeight = id;
EditMB = id;
EditModemDevice = id;
EditPrinterDevice = id;
EditROMpath = id;
EditWidth = id;
RemoveSCSI = id;
RemoveVolume = id;
ShowPrefs = id;
};
CLASS = PrefsEditor;
LANGUAGE = ObjC;
OUTLETS = {
CPU68000 = id;
CPU68020 = id;
CPU68030 = id;
CPU68040 = id;
FPU = id;
IIci = id;
MB = id;
Quadra900 = id;
ROMfile = id;
SCSIdisks = id;
bootFromAny = id;
bootFromCD = id;
bytes = id;
classic = id;
delay = id;
depth = id;
disableCD = id;
disableSound = id;
diskImages = id;
etherNet = id;
extFS = id;
frequency = id;
height = id;
modem = id;
panel = id;
printer = id;
width = id;
};
SUPERCLASS = NSObject;
}
);
IBVersion = 1;
}

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>IBDocumentLocation</key>
<string>5 42 473 240 0 41 1024 705 </string>
<key>IBMainMenuLocation</key>
<string>0 702 365 44 0 42 1152 704 </string>
<key>IBUserGuides</key>
<dict>
<key>About</key>
<dict>
<key>guideLocations</key>
<array/>
<key>guidesLocked</key>
<string>NO</string>
</dict>
</dict>
</dict>
</plist>

View File

@ -1,32 +0,0 @@
{
IBClasses = (
{
ACTIONS = {NewEmulator = id; ShowAbout = id; pauseAll = id; terminateAll = id; };
CLASS = Controller;
LANGUAGE = ObjC;
OUTLETS = {myEmulator = id; };
SUPERCLASS = NSObject;
},
{
ACTIONS = {
Interrupt = id;
PowerKey = id;
Restart = id;
Resume = id;
Snapshot = id;
SpeedChange = id;
Suspend = id;
Terminate = id;
ToggleState = id;
ZapPRAM = id;
};
CLASS = Emulator;
LANGUAGE = ObjC;
OUTLETS = {barberPole = id; runOrPause = id; screen = id; speed = id; win = id; };
SUPERCLASS = NSObject;
},
{CLASS = EmulatorView; LANGUAGE = ObjC; SUPERCLASS = NSView; },
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
);
IBVersion = 1;
}

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>IBDocumentLocation</key>
<string>18 42 473 240 0 41 1024 705 </string>
<key>IBMainMenuLocation</key>
<string>0 702 365 44 0 41 1024 705 </string>
<key>IBUserGuides</key>
<dict>
<key>Window</key>
<dict>
<key>guideLocations</key>
<array/>
<key>guidesLocked</key>
<string>NO</string>
</dict>
</dict>
</dict>
</plist>

View File

@ -1,5 +0,0 @@
This is a version of the interface that would allow multiple emulations to
run side-by-side, in different windows. Currently, the uae_cpu engine is not
re-entrant, and some of the Basilisk glue would not allow this, so this will
probably never be used. I will save it here for educational purposes, and just
in case this feature is ever needed.

View File

@ -1,91 +0,0 @@
//
// NNThread.h -Not Nextstep Thread?
// Nigel's Nice Thread?
//
// Revision 1.2, Tuesday May 25 2004
//
// Created by Nigel Pearson on Tue Nov 28 2000.
// Public Domain. No rights reserved.
//
// Define what flavour of threading to use:
#define USE_NSTHREAD
//#define USE_PTHREAD
#import <Cocoa/Cocoa.h>
#import <mach/mach.h>
#import <mach/kern_return.h>
#ifdef USE_PTHREAD
#include <pthread.h>
struct pthreadArgs // This duplicates most of the stuff in the NNThread object
{
id *object;
SEL *sel;
NSAutoreleasePool *pool;
BOOL allocPool,
*completed;
};
#endif
@interface NNThread : NSObject
{
id object;
SEL sel;
thread_t machThread;
#ifdef USE_PTHREAD
pthread_t pThread;
struct pthreadArgs pthreadArgs;
#endif
NSAutoreleasePool *pool;
BOOL allocPool,
completed,
suspended;
}
- (NNThread *) initWithAutoReleasePool;
- (NNThread *) initSuspended: (BOOL) startSuspended
withAutoreleasePool: (BOOL) allocatePool;
- (void) perform: (SEL)action of: (id)receiver;
- (void) resume;
- (BOOL) start;
- (void) suspend;
- (void) terminate;
@end
typedef enum _NNTimeUnits
{
NNnanoSeconds = 1,
NNmicroSeconds = 2,
NNmilliSeconds = 3,
NNseconds = 4
}
NNTimeUnits;
#import <sys/time.h>
@interface NNTimer : NNThread
{
struct timespec delay;
BOOL repeating;
id timerObject;
SEL timerSel;
}
- (NNTimer *) initWithAutoRelPool;
- (void) changeIntervalTo: (int)number units: (NNTimeUnits)units;
- (void) invalidate;
- (void) perform: (SEL)action of: (id)receiver
after: (int)number units: (NNTimeUnits)units;
- (void) repeat: (SEL)action of: (id)receiver
every: (int)number units: (NNTimeUnits)units;
@end

View File

@ -1,257 +0,0 @@
//
// NNThread.m -Not Nextstep Thread?
// Nigel's Nice Thread?
//
// Revision 1.4, Tuesday May 25 2004
//
// Created by Nigel Pearson on Tue Nov 28 2000.
// Public Domain. No rights reserved.
//
#import "NNThread.h"
#import <objc/objc-runtime.h> // For objc_msgSend() prototype
@implementation NNThread
// Define the wrapper first so that init knows about it without having to put it in the .h
#ifdef USE_NSTHREAD
- (void) wrapper
{
machThread = mach_thread_self();
if ( object == nil || sel == (SEL) nil || suspended )
thread_suspend (machThread); // Suspend myself
if ( allocPool )
pool = [NSAutoreleasePool new];
// [object sel] caused "cannot find method" warnings, so I do it a non-obvious way:
objc_msgSend (object, sel);
completed = YES;
if ( allocPool )
[pool release];
}
#endif
#ifdef USE_PTHREAD
void *
pthreadWrapper (void *arg)
{
struct pthreadArgs *args = arg;
if ( args -> allocPool )
args -> pool = [NSAutoreleasePool new];
objc_msgSend (*(args->object), *(args->sel));
*(args->completed) = YES;
if ( args -> allocPool )
[args -> pool release];
return NULL;
}
- (BOOL) wrapper
{
int error;
pthreadArgs.object = &object;
pthreadArgs.sel = &sel;
pthreadArgs.allocPool = allocPool;
pthreadArgs.completed = &completed;
pthreadArgs.pool = nil;
if ( object == nil || sel == (SEL) nil || suspended )
error = pthread_create_suspended_np (&pThread, NULL, &pthreadWrapper, &pthreadArgs);
else
error = pthread_create (&pThread, NULL, &pthreadWrapper, &pthreadArgs);
if ( error )
NSLog(@"%s - pthread_create failed");
else
machThread = pthread_mach_thread_np (pThread);
return ! error;
}
#endif
- (NNThread *) initSuspended: (BOOL) startSuspended
withAutoreleasePool: (BOOL) allocatePool
{
self = [super init];
allocPool = allocatePool;
completed = NO;
suspended = startSuspended;
object = nil;
sel = (SEL) nil;
#ifdef USE_NSTHREAD
[NSThread detachNewThreadSelector:@selector(wrapper)
toTarget:self
withObject:nil];
#endif
#ifdef USE_PTHREAD
if ( ! [self wrapper] ) // Wrapper does the thread creation
{
NSLog(@"%s - pthread wrapper failed", __PRETTY_FUNCTION__);
return nil;
}
#endif
return self;
}
- (NNThread *) init
{
return [self initSuspended: YES withAutoreleasePool: NO];
}
- (NNThread *) initWithAutoReleasePool
{
return [self initSuspended: YES withAutoreleasePool: YES];
}
- (BOOL) completed
{
return completed;
}
- (void) perform: (SEL)action of: (id)receiver
{
object = receiver, sel = action;
}
- (void) resume
{
if ( suspended )
[self start];
else
NSLog (@"%s - thread not suspended", __PRETTY_FUNCTION__);
}
- (BOOL) start
{
kern_return_t error;
if ( object == nil || sel == (SEL) nil )
{
NSLog (@"%s - cannot start thread, object or selector invalid", __PRETTY_FUNCTION__);
return NO;
}
if ( ( error = thread_resume (machThread) ) != KERN_SUCCESS )
NSLog (@"%s - thread_resume() failed, returned %d", __PRETTY_FUNCTION__, error);
suspended = NO;
return YES;
}
- (void) suspend
{
if ( ! suspended )
{
kern_return_t error;
if ( ( error = thread_suspend (machThread) ) != KERN_SUCCESS )
NSLog (@"%s - thread_resume() failed, returned %d", __PRETTY_FUNCTION__, error);
suspended = YES;
}
}
- (void) terminate
{
kern_return_t error;
if ( ( error = thread_terminate (machThread) ) != KERN_SUCCESS )
NSLog (@"%s - thread_terminate() failed, returned %d", __PRETTY_FUNCTION__, error);
}
@end
@implementation NNTimer
- (NNTimer *) init
{
self = [super init];
repeating = YES;
return self;
}
- (NNTimer *) initWithAutoRelPool
{
self = [super init];
allocPool = YES;
repeating = YES;
return self;
}
- (void) changeIntervalTo: (int)number
units: (NNTimeUnits)units
{
switch ( units )
{
case NNnanoSeconds:
delay.tv_nsec = number;
delay.tv_sec = 0;
break;
case NNmicroSeconds:
delay.tv_nsec = number * 1000;
delay.tv_sec = 0;
break;
case NNmilliSeconds:
delay.tv_nsec = number * 1000000;
delay.tv_sec = 0;
break;
case NNseconds:
delay.tv_nsec = 0;
delay.tv_sec = number;
break;
default:
NSLog (@"%s illegal units(%d)", __PRETTY_FUNCTION__, units);
}
}
- (void) invalidate
{
repeating = NO;
}
- (void) timerLoop
{
// For some strange reason, Mac OS X does not have this prototype
extern int nanosleep (const struct timespec *rqtp, struct timespec *rmtp);
while ( repeating )
{
nanosleep(&delay, NULL);
completed = NO;
// This caused a few warnings:
// [timerObject timerSel];
// so I do it a non-obvious way:
objc_msgSend (timerObject, timerSel);
completed = YES;
}
}
- (void) perform: (SEL)action of: (id)receiver
after: (int)number units: (NNTimeUnits)units
{
object = self, sel = @selector(timerLoop),
timerObject = receiver, timerSel = action, repeating = NO;
[self changeIntervalTo: number units: units];
}
- (void) repeat: (SEL)action of: (id)receiver
every: (int)number units: (NNTimeUnits)units
{
object = self, sel = @selector(timerLoop),
timerObject = receiver, timerSel = action, repeating = YES;
[self changeIntervalTo: number units: units];
}
@end

View File

@ -1,145 +0,0 @@
/*
* PrefsEditor.h - GUI stuff for Basilisk II preferences
* (which is a text file in the user's home directory)
*
* $Id$
*
* 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
*/
#import <Cocoa/Cocoa.h>
@interface TableDS : NSObject
{
int numItems;
NSMutableArray *col1,
*col2;
}
- (void) addInt: (int)target
withPath: (NSString *)path;
- (void) addObject: (NSObject *)obj
withPath: (NSString *)path;
- (void) deleteAll;
- (BOOL) deleteRow: (int)row;
- (int) intAtRow: (int)row;
- (int) numberOfRowsInTableView: (NSTableView *)tView;
- (NSString *) pathAtRow: (int)row;
- (id) tableView: (NSTableView *)tView
objectValueForTableColumn: (NSTableColumn *)tColumn
row: (int)rowIndex;
@end
#include "Emulator.h"
@interface PrefsEditor : NSObject
{
IBOutlet NSSlider *emuFreq;
IBOutlet NSView *newVolumeView;
IBOutlet NSTextField *newVolumeSize;
IBOutlet NSWindow *panel;
IBOutlet Emulator *theEmulator;
IBOutlet NSButton *bootFromAny,
*bootFromCD;
IBOutlet NSTextField *bytes;
IBOutlet NSButton *classic,
*CPU68000,
*CPU68020,
*CPU68030,
*CPU68040;
IBOutlet NSTextField *delay,
*depth;
IBOutlet NSButton *disableCD,
*disableSound;
IBOutlet NSTableView *diskImages;
IBOutlet NSTextField *etherNet,
*extFS;
IBOutlet NSButton *FPU;
IBOutlet NSTextField *frequency,
*height;
IBOutlet NSButton *IIci;
IBOutlet NSPopUpButton *keyboard;
IBOutlet NSTextField *MB,
*modem;
IBOutlet NSButton *openGL;
IBOutlet NSTextField *prefsFile,
*printer;
IBOutlet NSButton *quadra900;
IBOutlet NSTextField *ROMfile;
IBOutlet NSButton *screen;
IBOutlet NSTableView *SCSIdisks;
IBOutlet NSTextField *width;
IBOutlet NSButton *window;
NSString *devs,
*home;
TableDS *volsDS, // Object managing tha data in the Volumes,
*SCSIds; // and SCSI devices, tables
NSImage *locked,
*blank;
NSImageCell *lockCell;
BOOL edited; // Set if the user changes anything, reset on save
}
- (BOOL) hasEdited;
- (NSWindow *) window;
- (IBAction) AddSCSI: (id)sender;
- (IBAction) AddVolume: (id)sender;
- (IBAction) BrowseExtFS: (id)sender;
- (IBAction) BrowsePrefs: (id)sender;
- (IBAction) BrowseROM: (id)sender;
- (IBAction) ChangeBootFrom: (NSMatrix *)sender;
- (IBAction) ChangeCPU: (NSMatrix *)sender;
- (IBAction) ChangeDisableCD: (NSButton *)sender;
- (IBAction) ChangeDisableSound:(NSButton *)sender;
- (IBAction) ChangeFPU: (NSButton *)sender;
- (IBAction) ChangeKeyboard: (NSPopUpButton *)sender;
- (IBAction) ChangeModel: (NSMatrix *)sender;
- (IBAction) ChangeScreen: (id)sender;
- (IBAction) CreateVolume: (id)sender;
- (IBAction) DeleteVolume: (id)sender;
- (IBAction) EditBytes: (NSTextField *)sender;
- (IBAction) EditDelay: (NSTextField *)sender;
- (IBAction) EditEtherNetDevice:(NSTextField *)sender;
- (IBAction) EditExtFS: (NSTextField *)sender;
- (IBAction) EditFrequency: (NSTextField *)sender;
- (IBAction) EditMB: (NSTextField *)sender;
- (IBAction) EditModemDevice: (NSTextField *)sender;
- (IBAction) EditPrinterDevice: (NSTextField *)sender;
- (IBAction) EditROMpath: (NSTextField *)sender;
- (IBAction) LoadPrefs: (id)sender;
- (IBAction) RemoveSCSI: (id)sender;
- (IBAction) RemoveVolume: (id)sender;
- (NSString *) RemoveVolumeEntry;
- (IBAction) ResetPrefs: (id)sender;
- (IBAction) ShowPrefs: (id)sender;
- (IBAction) SavePrefs: (id)sender;
@end

View File

@ -1,844 +0,0 @@
/*
* PrefsEditor.m - GUI stuff for Basilisk II preferences
* (which is a text file in the user's home directory)
*
* $Id$
*
* 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
*/
#import "PrefsEditor.h"
@implementation TableDS
- (TableDS *) init
{
self = [super init];
numItems = 0;
col1 = [NSMutableArray new];
col2 = [NSMutableArray new];
return self;
}
- (void) dealloc
{
[col1 dealloc];
[col2 dealloc];
[super dealloc];
}
- (void) addInt: (int)target
withPath: (NSString *)path
{
[col1 addObject: [NSNumber numberWithInt: target]];
[col2 addObject: path];
++numItems;
}
- (void) addObject: (NSObject *)obj
withPath: (NSString *)path
{
[col1 addObject: obj];
[col2 addObject: path];
++numItems;
}
- (void) deleteAll
{
numItems = 0;
[col1 removeAllObjects];
[col2 removeAllObjects];
}
- (BOOL) deleteRow: (int)row
{
if ( row > numItems )
return NO;
[col1 removeObjectAtIndex: row];
[col2 removeObjectAtIndex: row];
-- numItems;
return YES;
}
- (int)intAtRow: (int)row
{
return [[col1 objectAtIndex: row] intValue];
}
- (int) numberOfRowsInTableView: (NSTableView *)tView
{
return numItems;
}
- (NSString *)pathAtRow: (int)row
{
return (NSString *) [col2 objectAtIndex: row];
}
- (id) tableView: (NSTableView *)tView
objectValueForTableColumn: (NSTableColumn *)tColumn
row: (int)row
{
if ( [[tColumn identifier] isEqualToString:@"path"] )
return [col2 objectAtIndex: row];
else
return [col1 objectAtIndex: row];
}
@end
#import <AppKit/NSImage.h> // For [NSBundle pathForImageResource:] proto
#include <string>
using std::string;
extern string UserPrefsPath; // from prefs_unix.cpp
#import "sysdeps.h" // Types used in Basilisk C++ code
#import "video_macosx.h" // some items that we edit here
#import "misc_macosx.h" // WarningSheet() prototype
#import "main_macosx.h" // ChoiceAlert() prototype
#import <prefs.h>
#define DEBUG 0
#import <debug.h>
@implementation PrefsEditor
- (PrefsEditor *) init
{
self = [super init];
edited = NO;
devs = @"/dev";
home = [NSHomeDirectory() retain];
volsDS = [TableDS new];
SCSIds = [TableDS new];
lockCell = [NSImageCell new];
if ( lockCell == nil )
NSLog (@"%s - Can't create NSImageCell?", __PRETTY_FUNCTION__);
blank = [NSImage new];
locked = [[NSImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForImageResource: @"nowrite.icns"]];
if (locked == nil )
NSLog(@"%s - Couldn't open write protection image", __PRETTY_FUNCTION__);
return self;
}
- (void) dealloc
{
[home release];
[volsDS release];
[SCSIds release];
[lockCell release];
[blank release];
[locked release];
[super dealloc];
}
- (void) awakeFromNib
{
emuFreq = [theEmulator speed];
#if DEBUG
[self ShowPrefs: self]; // For testing
#endif
}
- (BOOL) hasEdited
{
return edited;
}
- (NSWindow *) window
{
return panel;
}
- (IBAction) AddSCSI: (id)sender
{
NSOpenPanel *oP = [NSOpenPanel openPanel];
if ( [oP runModalForDirectory:home file:nil types:nil] == NSOKButton )
{
[SCSIds addInt: -1
withPath: [oP filename] ];
[SCSIdisks reloadData];
edited = YES;
}
}
- (IBAction) AddVolume: (id)sender
{
NSOpenPanel *oP = [NSOpenPanel openPanel];
if ( [oP runModalForDirectory:home file:nil types:nil] == NSOKButton )
{
[volsDS addObject: (NSObject *) locked
withPath: [oP filename] ];
PrefsAddString("disk", [[oP filename] UTF8String]);
[diskImages reloadData];
edited = YES;
}
}
- (IBAction) BrowseExtFS: (id)sender
{
NSOpenPanel *oP = [NSOpenPanel openPanel];
[oP setCanChooseDirectories: YES];
[oP setCanChooseFiles: NO];
[oP setPrompt: @"Select"];
[oP setTitle: @"Select a directory to mount"];
D(NSLog(@"%s - home = %@, [extFS stringValue] = %@",
__PRETTY_FUNCTION__, home, [extFS stringValue]));
if ( [oP runModalForDirectory: ([extFS stringValue] ? [extFS stringValue] : home)
file:nil
types:nil] == NSOKButton )
{
[extFS setStringValue: [oP directory] ];
PrefsReplaceString("extfs", [[oP directory] UTF8String]);
edited = YES;
}
}
- (IBAction) BrowsePrefs: (id)sender
{
NSOpenPanel *oP = [NSOpenPanel openPanel];
[oP setCanChooseFiles: YES];
[oP setTitle: @"Select a Preferences file"];
D(NSLog(@"%s - home = %@", __PRETTY_FUNCTION__, home));
if ( [oP runModalForDirectory: ([prefsFile stringValue] ? [prefsFile stringValue] : home)
file:nil
types:nil] == NSOKButton )
{
[prefsFile setStringValue: [oP filename] ];
UserPrefsPath = [[oP filename] UTF8String];
}
}
- (IBAction) BrowseROM: (id)sender
{
NSOpenPanel *oP = [NSOpenPanel openPanel];
[oP setCanChooseFiles: YES];
[oP setTitle: @"Open a ROM file"];
D(NSLog(@"%s - home = %@", __PRETTY_FUNCTION__, home));
if ( [oP runModalForDirectory: ([ROMfile stringValue] ? [ROMfile stringValue] : home)
file:nil
types:nil] == NSOKButton )
{
[ROMfile setStringValue: [oP filename] ];
PrefsReplaceString("rom", [[oP filename] UTF8String]);
edited = YES;
}
}
#include <cdrom.h> // for CDROMRefNum
- (IBAction) ChangeBootFrom: (NSMatrix *)sender
{
if ( [sender selectedCell] == (id)bootFromCD )
{
[disableCD setState: NSOffState];
PrefsReplaceInt32("bootdriver", CDROMRefNum);
}
else
PrefsReplaceInt32("bootdriver", 0);
edited = YES;
}
- (IBAction) ChangeCPU: (NSMatrix *)sender
{
PrefsReplaceInt32("cpu", [[sender selectedCell] tag]);
edited = YES;
}
- (IBAction) ChangeDisableCD: (NSButton *)sender
{
int disabled = [disableCD state];
PrefsReplaceBool("nocdrom", disabled);
if ( disabled )
{
[bootFromAny setState: NSOnState];
[bootFromCD setState: ![disableCD state]];
}
edited = YES;
}
- (IBAction) ChangeDisableSound: (NSButton *)sender
{
BOOL noSound = [disableSound state];
if ( ! noSound )
WarningSheet(@"Sound is currently unimplemented", panel);
PrefsReplaceBool("nosound", noSound);
edited = YES;
}
- (IBAction) ChangeFPU: (NSButton *)sender
{
PrefsReplaceBool("fpu", [FPU state]);
edited = YES;
}
- (IBAction) ChangeKeyboard: (NSPopUpButton *)sender
{
// Deselest current item
int current = [keyboard indexOfItemWithTag: PrefsFindInt32("keyboardtype")];
if ( current != -1 )
[[keyboard itemAtIndex: current] setState: FALSE];
PrefsReplaceInt32("keyboardtype", [[sender selectedItem] tag]);
edited = YES;
}
- (IBAction) ChangeModel: (NSMatrix *)sender
{
PrefsReplaceInt32("modelid", [[sender selectedCell] tag]);
edited = YES;
}
// If we are not using the CGIMAGEREF drawing strategy,
// then source bitmaps must be 32bits deep.
- (short) testWinDepth: (int) newbpp
{
#ifdef CGIMAGEREF
return newbpp;
#else
if ( newbpp != 32 )
WarningSheet(@"Sorry - In windowed mode, depth must be 32", panel);
return 32;
#endif
}
// This is called when the screen/window,
// width, height or depth is clicked.
//
// Note that sender may not actually be an NSMatrix.
- (IBAction) ChangeScreen: (NSMatrix *)sender
{
NSButton *cell = [sender selectedCell];
short newx = [width intValue];
short newy = [height intValue];
short newbpp = [depth intValue];
short newtype;
char str[20];
if ( cell == screen )
newtype = DISPLAY_SCREEN;
else if ( cell == window )
newtype = DISPLAY_WINDOW;
else
newtype = display_type;
// Check that a field actually changed
if ( newbpp == init_depth && newx == init_width &&
newy == init_height && newtype == display_type )
{
D(NSLog(@"No changed GUI items in ChangeScreen"));
return;
}
// If we are changing type, supply some sensible defaults
short screenx = CGDisplayPixelsWide(kCGDirectMainDisplay),
screeny = CGDisplayPixelsHigh(kCGDirectMainDisplay),
screenb = CGDisplayBitsPerPixel(kCGDirectMainDisplay);
if ( newtype != display_type )
{
D(NSLog(@"Changing display type in ChangeScreen"));
// If changing to full screen, supply main screen dimensions as a default
if ( newtype == DISPLAY_SCREEN )
newx = screenx, newy = screeny, newbpp = screenb;
// If changing from full screen, use minimum screen resolutions
if ( display_type == DISPLAY_SCREEN )
{
newx = MIN_WIDTH, newy = MIN_HEIGHT;
newbpp = [self testWinDepth: newbpp];
}
}
else
{
newbpp = [self testWinDepth: newbpp];
// Check size is within ranges of MIN_WIDTH ... MAX_WIDTH
// and MIN_HEIGHT ... MAX_HEIGHT
// ???
}
[width setIntValue: newx];
[height setIntValue: newy];
[depth setIntValue: newbpp];
// Store new prefs
*str = '\0';
switch ( newtype )
{
case DISPLAY_WINDOW:
if ( newbpp )
sprintf(str, "win/%hd/%hd/%hd", newx, newy, newbpp);
else
sprintf(str, "win/%hd/%hd", newx, newy);
break;
case DISPLAY_SCREEN:
if ( newbpp )
sprintf(str, "full/%hd/%hd/%hd", newx, newy, newbpp);
else
sprintf(str, "full/%hd/%hd", newx, newy);
break;
};
PrefsReplaceString("screen", str);
parse_screen_prefs(str);
edited = YES;
if ( display_type != DISPLAY_SCREEN )
{
D(NSLog(@"Display type is not SCREEN (%d), resizing window",
display_type));
resizeWinTo(newx, newy);
}
}
- (IBAction) CreateVolume: (id)sender
{
NSSavePanel *sP = [NSSavePanel savePanel];
[sP setAccessoryView: newVolumeView];
[sP setPrompt: @"Create"];
[sP setTitle: @"Create new volume as"];
if ( [sP runModalForDirectory:NSHomeDirectory() file:@"basilisk-II.vol"] == NSOKButton )
{
char cmd[1024];
const char *filename = [[sP filename] UTF8String];
int retVal,
size = [newVolumeSize intValue];
sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", filename, size);
retVal = system(cmd);
if (retVal != 0)
{
NSString *details = [NSString stringWithFormat:
@"The dd command failed.\nReturn status %d (%s)",
retVal, strerror(errno)];
WarningSheet(@"Unable to create volume", details, nil, panel);
}
else
{
[volsDS addObject: (NSObject *) blank
withPath: [sP filename] ];
PrefsAddString("disk", filename);
[diskImages reloadData];
}
}
}
- (BOOL) fileManager: (NSFileManager *) manager
shouldProceedAfterError: (NSDictionary *) errorDict
{
NSRunAlertPanel(@"File operation error",
@"%@ %@, toPath %@",
@"Bugger!", nil, nil,
[errorDict objectForKey:@"Error"],
[errorDict objectForKey:@"Path"],
[errorDict objectForKey:@"ToPath"]);
return NO;
}
- (IBAction) DeleteVolume: (id)sender
{
NSString *Path = [self RemoveVolumeEntry];
if ( ! Path )
return;
if ( ! [[NSFileManager defaultManager] removeFileAtPath: Path
handler: self] )
{
WarningSheet(@"Unable to delete volume", panel);
NSLog(@"%s unlink(%s) failed - %s", __PRETTY_FUNCTION__,
[Path cString], strerror(errno));
}
}
- (IBAction) EditDelay: (NSTextField *)sender
{
int ticks = [delay intValue];
float freq;
if ( ticks )
freq = 60.0 / ticks;
else
freq = 60.0;
[frequency setFloatValue: freq];
[emuFreq setFloatValue: freq];
PrefsReplaceInt32("frameskip", ticks);
edited = YES;
}
- (IBAction) EditBytes: (NSTextField *)sender
{
int B = (int) [bytes floatValue];
float M = B / 1024 / 1024;
D(NSLog(@"%s = %f %d", __PRETTY_FUNCTION__, M, B));
PrefsReplaceInt32("ramsize", B);
[MB setFloatValue: M];
edited = YES;
}
- (IBAction) EditEtherNetDevice: (NSTextField *)sender
{
NSString *path = [etherNet stringValue];
PrefsReplaceString("ether", [path UTF8String]);
edited = YES;
}
- (IBAction) EditExtFS: (NSTextField *)sender
{
NSString *path = [extFS stringValue];
PrefsReplaceString("extfs", [path UTF8String]);
edited = YES;
}
- (IBAction) EditFrequency: (NSTextField *)sender
{
float freq = [frequency floatValue];
[delay setIntValue: frequencyToTickDelay(freq)];
[emuFreq setFloatValue: freq];
edited = YES;
}
- (IBAction) EditModemDevice: (NSTextField *)sender
{
NSString *path = [modem stringValue];
PrefsReplaceString("seriala", [path UTF8String]);
edited = YES;
}
- (IBAction) EditMB: (NSTextField *)sender
{
float M = [MB floatValue];
int B = (int) (M * 1024 * 1024);
D(NSLog(@"%s = %f %d", __PRETTY_FUNCTION__, M, B));
PrefsReplaceInt32("ramsize", B);
[bytes setIntValue: B];
edited = YES;
}
- (IBAction) EditPrinterDevice: (NSTextField *)sender
{
NSString *path = [printer stringValue];
PrefsReplaceString("serialb", [path UTF8String]);
edited = YES;
}
- (IBAction) EditROMpath: (NSTextField *)sender
{
NSString *path = [ROMfile stringValue];
PrefsReplaceString("rom", [path UTF8String]);
}
- (IBAction) RemoveSCSI: (id)sender
{
char pref[6];
int row = [SCSIdisks selectedRow],
SCSIid = [SCSIds intAtRow: row];
if ( ! [SCSIds deleteRow: row] )
NSLog (@"%s - [SCSIds deleteRow: %d] failed", __PRETTY_FUNCTION__, row);
[SCSIdisks reloadData];
sprintf(pref, "scsi%d", SCSIid);
//PrefsRemoveItem(pref,0);
PrefsRemoveItem(pref, 1);
}
- (NSString *) RemoveVolumeEntry
{
int row = [diskImages selectedRow];
if ( row != -1 )
{
NSString *Path = [volsDS pathAtRow: row];
const char *path = [Path UTF8String],
*str;
int tmp = 0;
NSString *prompt = [NSString stringWithFormat: @"%s\n%s",
"Are you sure you want to delete the file",
path];
if ( ! ChoiceAlert([prompt cString], "Delete", "Cancel") )
return NULL;
while ( (str = PrefsFindString("disk", tmp) ) != NULL )
{
if ( strcmp(str, path) == 0 )
{
PrefsRemoveItem("disk", tmp);
D(NSLog(@"%s - Deleted prefs entry \"disk\", %d",
__PRETTY_FUNCTION__, tmp));
edited = YES;
break;
}
++tmp;
}
if ( str == NULL )
{
NSLog(@"%s - Couldn't find any disk preference to match %s",
__PRETTY_FUNCTION__, path);
return NULL;
}
if ( ! [volsDS deleteRow: row] )
NSLog (@"%s - RemoveVolume %d failed", __PRETTY_FUNCTION__, tmp);
[diskImages reloadData];
// return path;
return Path;
}
else
{
WarningSheet(@"Please select a volume first", panel);
return NULL;
}
}
- (IBAction) RemoveVolume: (id)sender
{
[self RemoveVolumeEntry];
}
- (void) loadPrefs: (int) argc
args: (char **) argv
{
[panel close]; // Temporarily hide preferences panel
PrefsExit(); // Purge all the old pref values
PrefsInit(NULL, argc, argv);
AddPrefsDefaults();
AddPlatformPrefsDefaults(); // and only create basic ones
[SCSIds deleteAll]; // Clear out datasources for the tables
[volsDS deleteAll];
[self ShowPrefs: self]; // Reset items in panel, and redisplay
edited = NO;
}
- (IBAction) LoadPrefs: (id)sender
{
int argc = 2;
char *argv[2];
argv[0] = "--prefs",
argv[1] = (char *) [[prefsFile stringValue] UTF8String];
[self loadPrefs: argc
args: argv];
}
- (IBAction) ResetPrefs: (id)sender
{
[self loadPrefs: 0
args: NULL];
}
- (void) setStringOf: (NSTextField *) field
fromPref: (const char *) prefName
{
const char *value = PrefsFindString(prefName, 0);
if ( value )
[field setStringValue: [NSString stringWithUTF8String: value] ];
}
- (IBAction) SavePrefs: (id)sender
{
SavePrefs();
edited = NO;
}
- (IBAction) ShowPrefs: (id)sender
{
NSTableColumn *locks;
const char *str;
int cpu, tmp, val;
// Set simple single field items
val = PrefsFindInt32("frameskip");
[delay setIntValue: val];
if ( val )
[frequency setFloatValue: 60.0 / val];
else
[frequency setFloatValue: 60.0];
val = PrefsFindInt32("ramsize");
[bytes setIntValue: val];
[MB setFloatValue: val / (1024.0 * 1024.0)];
[disableCD setState: PrefsFindBool("nocdrom")];
[disableSound setState: PrefsFindBool("nosound")];
[FPU setState: PrefsFindBool("fpu") ];
[self setStringOf: etherNet fromPref: "ether" ];
[self setStringOf: extFS fromPref: "extfs" ];
[self setStringOf: modem fromPref: "seriala"];
[self setStringOf: printer fromPref: "serialb"];
[self setStringOf: ROMfile fromPref: "rom"];
[prefsFile setStringValue: [NSString stringWithUTF8String: UserPrefsPath.c_str()] ];
parse_screen_prefs(PrefsFindString("screen"));
[width setIntValue: init_width];
[height setIntValue: init_height];
[depth setIntValue: init_depth];
[screen setState: NO];
switch ( display_type )
{
case DISPLAY_WINDOW: [window setState: YES]; break;
case DISPLAY_SCREEN: [screen setState: YES]; break;
}
[newVolumeSize setIntValue: 10];
// Radio button groups:
val = PrefsFindInt32("bootdriver");
[bootFromAny setState: val != CDROMRefNum];
[bootFromCD setState: val == CDROMRefNum];
cpu = PrefsFindInt32("cpu");
val = PrefsFindInt32("modelid");
#if REAL_ADDRESSING || DIRECT_ADDRESSING
puts("Current memory model does not support 24bit addressing");
if ( val == [classic tag] )
{
// Window already created by NIB file, just display
[panel makeKeyAndOrderFront:self];
WarningSheet(@"Compiled-in memory model does not support 24bit",
@"Disabling Mac Classic emulation", nil, panel);
cpu = [CPU68030 tag];
PrefsReplaceInt32("cpu", cpu);
val = [IIci tag];
PrefsReplaceInt32("modelid", val);
}
puts("Disabling 68000 & Mac Classic buttons");
[CPU68000 setEnabled:FALSE];
[classic setEnabled:FALSE];
#endif
[CPU68000 setState: [CPU68000 tag] == cpu];
[CPU68020 setState: [CPU68020 tag] == cpu];
[CPU68030 setState: [CPU68030 tag] == cpu];
[CPU68040 setState: [CPU68040 tag] == cpu];
[classic setState: [classic tag] == val];
[IIci setState: [IIci tag] == val];
[quadra900 setState: [quadra900 tag] == val];
// Lists of thingies:
val = PrefsFindInt32("keyboardtype");
tmp = [keyboard indexOfItemWithTag: val];
if ( tmp != -1 )
[keyboard selectItemAtIndex: tmp];
for ( tmp = 0; tmp < [keyboard numberOfItems]; ++tmp )
{
NSMenuItem *type = [keyboard itemAtIndex: tmp];
[type setState: [type tag] == val];
}
for ( tmp = 0; tmp < 7; ++tmp)
{
char pref[6];
pref[0] = '\0';
sprintf (pref, "scsi%d", tmp);
if ( (str = PrefsFindString(pref, 0) ) )
[SCSIds addInt: tmp
withPath: [NSString stringWithCString: str] ];
}
[SCSIdisks setDataSource: SCSIds];
locks = [diskImages tableColumnWithIdentifier: @"locked"];
if ( locks == nil )
NSLog (@"%s - Can't find column for lock images", __PRETTY_FUNCTION__);
[locks setDataCell: lockCell];
tmp = 0;
while ( (str = PrefsFindString("disk", tmp++) ) != NULL )
{
if ( *str == '*' )
[volsDS addObject: (NSObject *) locked
withPath: [NSString stringWithUTF8String: str+1]];
else
[volsDS addObject: (NSObject *) blank
withPath: [NSString stringWithUTF8String: str]];
}
[diskImages setDataSource: volsDS];
[panel makeKeyAndOrderFront:self]; // Window already created by NIB file, just display
}
@end

View File

@ -1,61 +0,0 @@
<!-- $Id$><-->
Bugs:
<UL>
<LI>In window mode, if the framerate is low (<I>e.g.</I> if you leave it at the
default of 10fps) or if the emulated screen is too large,
really fast mouse clicks are sometimes not picked up
by the Emulator. For now, click more slowly</LI>
<LI>In full screen mode after a restart, when the mouse is first moved,
the emulated pointer jumps to the location that it was before the restart.
Disturbing, but not damaging.</LI>
<LI>Ejecting a CD only works in 10.2 or higher, and it freezes the emulation
for about 5 seconds.</LI>
<LI>Status of 'dd' command is not always correct. (If it runs out of space,
an error about file not found is printed?)</LI>
<LI>The Snapshot function is currently broken in some situations
(if the emulation changes its own screen settings, and the program
is compiled with the default window drawing mode of CGIMAGEREF).
Setting the depth to millions (in the emulator) is a workaround for now</LI>
<LI>Cut and paste between emulator and OS X only half works</LI>
</UL>
Untested:
<UL>
<LI>Mac Classic emulation. I don't have a ROM, but I suspect it will crash</LI>
<LI>Serial port code</LI>
</UL>
Unimplemented:
<UL>
<LI>CD audio stuff. I am still trying to get this to work</LI>
<LI>CD insert detection. At the moment, if a CD isn't there when the
emulator boots, or if you change CDs, it will never know. I don't
know how to register with the OS for disk insertion and mount events.
(Gwenol&eacute; rewrote the CD code, and it should poll for new disks,
but it don't work for me. I must be doing something wrong!)</LI>
<LI>Floppy stuff. If a floppy is mounted by the OS X Finder,
it is busy and cannot be opened by the emulator</LI>
<LI>Interrupt function for emulator</LI>
<LI>'nogui' to disable GUI alerts (and maybe preferences, but I need to split
MainMenu.nib to do that)</LI>
</UL>
Possible Enhancements:
<UL>
<LI>Use NSFileManager's movePath:toPath:handler to rename all a file's forks
in extfs_macosx.mm</LI>
<LI>Emulator snapshot - save the current emulator state
(memory + registers) to a file for fast startup next time</LI>
<LI>Multiple emulators. The window stuff is mostly there,
but the uae_cpu code has lots of globals, and is not re-entrant</LI>
<LI>Real addressing mode for the emulator. Mike Sliczniak had done most of the
work, but with real addressing the emulator just crashes for me</LI>
<LI>Improve Objective-C object allocation. e.g. http://www.mulle-kybernetik.com/artikel/Optimisation/opti-5.html</LI>
<LI>Use automake instead of the current 1_prepare_files.sh ?</LI>
<LI>Add JIT options to preferences?</LI>
<LI>Use internal windows to display Help doco?</LI>
<LI>Provide feedback during external commands (<I>e.g.</I> ejecting a CD or
creating a disk volume)</LI>
<LI>Widescreen window layout (suggestion by Michael Franz), so that users
with widescreen displays can squeeze a bigger emulated screen in.
I have a mock up of this that can be pasted in (MainMenu.nib).
Ideally, this would be via a generalised "theme" facility,
but who has time for that :-)</LI>
</UL>

View File

@ -1,120 +0,0 @@
<!-- $Id$><-->
Versions of MacOS X port of Basilisk II:
<OL>
<LI>Initial port to Public Beta, made minor changes to get it to compile under Final Release.
<BR>Gave a copy of this version to Gwenol&eacute; Beauchesne (one of the other porters)</LI>
<LI>Ported to version 0.9 of the Basilisk II tarball.
<BR>Re-engineered autoconfig files to give a clean autoconf and make of cpu_uae code.
<BR>Fixed a bug in the EmulatorView class (I was customising release instead of dealloc).
<BR>Added:
<UL>
<LI>Transparency to icon</LI>
<LI>Port-specific doco: 0_HOW_TO_BUILD.txt, ToDo.html and Versions.html</LI>
<LI>Screen Snapshot code</LI>
<LI>Preferences saving and resetting</LI>
<LI>Delegate code, called when user attempts to close emulator window or quit application,
to check whether preferences need saving or application should be allowed to quit</LI>
<LI>ExtFS resource and type/creator access code</LI>
<LI>Window resizing stuff:
<OL>
<LI>The screensize can be set in the preferences. If the emulator has yet to
start then the window and emulator screen is resized. Otherwise, and</LI>
<LI>At any time, the window can be resized, which scales the emulator screen image</LI>
</OL>
</LI>
</UL>
Gave a copy of this to Max Horn</LI>
<LI>Some code fixes suggested by Max, doco updates, and porting to OS 10.1</LI>
<LI>Event handling re-write inspired by Max (subclassing NSApplication for custom sendEvent:).
Command key and double clicks are now passed correctly to the Emulator. Took out the custom
"About" window stuff, and added some credits (with an html link to the official Basilisk home
page) in the standard About box. Also has the standard README in the help menu.
<BR>Gave a copy to Max</LI>
<LI>Streamlining of event sending (filter mouseMoved events when not in Emulator screen)</LI>
<LI>Recompile in Project Builder, because the makefile generated binary dies at startup</LI>
<LI>Ported to the Basilisk II 1.0 snapshot's source and implemented video resolution switching.
Also uses Objective-C++, which eliminates some of the wrapper code which was previously needed.</LI>
<LI>Video preferences fixes, small tidyup of source.</LI>
<LI>Full screen mode added, more source tidied up.</LI>
<!-- v10><-->
<LI>Finally checked into CVS repository. Key event bug fixes:
<UL>
<LI>Cursor keys are now decoded and passed to the Emulator correctly</LI>
<LI>New one (in version 9) reported by Kentaro Nakatani -
full screen mode was not passing key events</LI>
</UL></LI>
<LI>Repaired help menu item, added documentation folder.</LI>
<LI>Several monitor resolution-changing fixes. Windowed mode now supports all depths,
and is up to 6 times faster. I now no longer have any plans to do an OpenGL mode.
<BR>Minor change in preferences (RAM size fields no longer require
the user to press return or enter for the value to "take").
<BR>Some modifications for compilation on 10.2 <I>and</I> 10.1
<BR>Initial CD-ROM reading code.</LI>
<LI>Restarting the emulator should be safe and fairly reliable,
and errors in starting the emulator should now be caught.
<BR>Resizing of window is now animated, and window is centred afterwards.
<BR>Reduced memory leaks when changing screensize in windowed mode.
<BR>Screen default pref is now Mac II (and not Classic) size.
<BR>Fixed:
<UL>
<LI>Bug where the Prefs could not be edited while the emulator was running</LI>
<LI>Help menu item (again) and added extra doco there</LI>
<LI>Preferences RAM size thing (again)</LI>
<LI>A minor Prefs editor button anomaly</LI>
</UL></LI>
<LI>Preferences file can now be specified on the command line,
and changed/loaded in the Preferences editor.
Added a feature from the windows port - now supports different keyboard types.
Changed:
<UL>
<LI>Default extfs; was '/', now user's home directory (Suggestion by Olaf Pluta.
Seeing all the Unix dirs <I>is</I> a bit scary!)</LI>
<LI>HowTo now displayed by default web browser (as it contains links)</LI>
<LI>Project Builder defaults so that debug symbols are not included</LI>
</UL></LI>
<LI>Now built on 10.3 and Xcode. Also adds:
<UL>
<LI>Xcode project files</LI>
<LI>Initial floppy and serial port locating code</LI>
<LI>Some help labels on the buttons
(some users didn't understand what the triangle button meant)</LI>
<LI>Signal handling for crash protection
(thanks to Mike Sliczniak's hard work)</LI>
</UL>
</LI>
<LI>Now distributed as two applications; the usual one (which should be faster),
and one for emulating a Mac Classic (which may also help the 10.2/10.3 users
who are having problems with a black screen at startup). The difference is
that the "classic" version uses virtual or "banks" memory addressing.
Fixed:
<UL>
<LI>Loading of ROM or disk images from directories or filenames which
contain non-ASCII characters</LI>
<LI>Floppy locating code. It can't actually access a floppy, but at
least it now won't add the cdrom multiple times</LI>
</UL>
</LI>
<LI>Working ethernet, without extra drivers, thanks to Gwenol&eacute;.
<BR>Lots of bug fixes by Bernie Zenis. Some 10.4 fixes by Kirk Kerekes.
<BR>Some fixes by Marcus Gail ( 'Boot From: CD-ROM' <I>vs</I>
'Disable CD-ROM Driver' clash).
<BR>Some cosmetic changes (widened RAM MB in prefs, added confirmation
when deleting volumes).
<BR>Now no need for "classic" version -
Gwenol&eacute; fixed the black screen problem</LI>
<LI>(actually 18a) Minor fixes:
<UL>
<LI>Mouse should always woork in fullscreen mode, and</LI>
<LI>If snapshot fails, the dialog makes a workaround suggestion</LI>
</UL>
</LI>
<LI>Updated the HowTo, external filesystem fix on 10.4, CD code rewrite.
Added some new features:
<UL>
<LI>Sound support by Daniel Sumorok! Thanks also to Dave Vasilevsky,
who produced earlier versions of sound code that I didn't use.</LI>
<LI>Cut & Paste support from Gwenol&eacute;. You can now paste from the OS X
clipboard into the emulator (pasting the other way doesn't work
for me yet)</LI>
</UL>
</OL>

View File

@ -1,80 +0,0 @@
/*
* $Id$
*
* audio_defs_macosx.h - Work around clashes with the enums in <CarbonCore/OSUtils.h>
* Based on:
*
* audio_defs.h - Definitions for MacOS audio components
*
* 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 AUDIO_DEFS_H
#define AUDIO_DEFS_H
#include "macos_util_macosx.h"
enum { // ComponentResource struct
componentType = 0,
componentSubType = 4,
componentManufacturer = 8,
componentFlags = 12,
componentFlagsMask = 16,
componentResType = 20,
componentResID = 24,
componentNameType = 26,
componentNameID = 30,
componentInfoType = 32,
componentInfoID = 36,
componentIconType = 38,
componentIconID = 42,
componentVersion = 44,
componentRegisterFlags = 48,
componentIconFamily = 52,
componentPFCount = 54,
componentPFFlags = 58,
componentPFResType = 62,
componentPFResID = 66,
componentPFPlatform = 68
};
enum { // ComponentParameters struct
cp_flags = 0, // call modifiers: sync/async, deferred, immed, etc
cp_paramSize = 1, // size in bytes of actual parameters passed to this call
cp_what = 2, // routine selector, negative for Component management calls
cp_params = 4 // actual parameters for the indicated routine
};
enum { // SoundComponentData struct
scd_flags = 0,
scd_format = 4,
scd_numChannels = 8,
scd_sampleSize = 10,
scd_sampleRate = 12,
scd_sampleCount = 16,
scd_buffer = 20,
scd_reserved = 24,
SIZEOF_scd = 28
};
enum { // SoundInfoList struct
sil_count = 0,
sil_infoHandle = 2
};
#endif

View File

@ -1,271 +0,0 @@
/*
* audio_macosx.cpp - Audio support, implementation Mac OS X
* Copyright (C) 2006, Daniel Sumorok
*
* 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/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include "cpu_emulation.h"
#include "main.h"
#include "prefs.h"
#include "user_strings.h"
#include "audio.h"
#include "audio_defs.h"
#include "MacOSX_sound_if.h"
#define DEBUG 0
#include "debug.h"
// The currently selected audio parameters (indices in
// audio_sample_rates[] etc. vectors)
static int audio_sample_rate_index = 0;
static int audio_sample_size_index = 0;
static int audio_channel_count_index = 0;
// Prototypes
static OSXsoundOutput *soundOutput = NULL;
static bool main_mute = false;
static bool speaker_mute = false;
/*
* Initialization
*/
static int audioInt(void);
static bool open_audio(void)
{
AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index];
AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index];
AudioStatus.channels = audio_channel_counts[audio_channel_count_index];
if (soundOutput)
delete soundOutput;
soundOutput = new OSXsoundOutput();
soundOutput->start(AudioStatus.sample_size, AudioStatus.channels,
AudioStatus.sample_rate >> 16);
soundOutput->setCallback(audioInt);
audio_frames_per_block = soundOutput->bufferSizeFrames();
audio_open = true;
return true;
}
void AudioInit(void)
{
// Sound disabled in prefs? Then do nothing
if (PrefsFindBool("nosound"))
return;
//audio_sample_sizes.push_back(8);
audio_sample_sizes.push_back(16);
audio_channel_counts.push_back(1);
audio_channel_counts.push_back(2);
audio_sample_rates.push_back(11025 << 16);
audio_sample_rates.push_back(22050 << 16);
audio_sample_rates.push_back(44100 << 16);
// Default to highest supported values
audio_sample_rate_index = audio_sample_rates.size() - 1;
audio_sample_size_index = audio_sample_sizes.size() - 1;
audio_channel_count_index = audio_channel_counts.size() - 1;
AudioStatus.mixer = 0;
AudioStatus.num_sources = 0;
audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
audio_component_flags = 0;
open_audio();
}
/*
* Deinitialization
*/
static void close_audio(void)
{
D(bug("Closing Audio\n"));
if (soundOutput)
{
delete soundOutput;
soundOutput = NULL;
}
audio_open = false;
}
void AudioExit(void)
{
// Close audio device
close_audio();
}
/*
* First source added, start audio stream
*/
void audio_enter_stream()
{
// Streaming thread is always running to avoid clicking noises
}
/*
* Last source removed, stop audio stream
*/
void audio_exit_stream()
{
// Streaming thread is always running to avoid clicking noises
}
/*
* MacOS audio interrupt, read next data block
*/
void AudioInterrupt(void)
{
D(bug("AudioInterrupt\n"));
uint32 apple_stream_info;
uint32 numSamples;
int16 *p;
M68kRegisters r;
if (!AudioStatus.mixer)
{
numSamples = 0;
soundOutput->sendAudioBuffer((void *)p, (int)numSamples);
D(bug("AudioInterrupt done\n"));
return;
}
// Get data from apple mixer
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]));
apple_stream_info = ReadMacInt32(audio_data + adatStreamInfo);
if (apple_stream_info && (main_mute == false) && (speaker_mute == false))
{
numSamples = ReadMacInt32(apple_stream_info + scd_sampleCount);
p = (int16 *)Mac2HostAddr(ReadMacInt32(apple_stream_info + scd_buffer));
}
else
{
numSamples = 0;
p = NULL;
}
soundOutput->sendAudioBuffer((void *)p, (int)numSamples);
D(bug("AudioInterrupt done\n"));
}
/*
* Set sampling parameters
* "index" is an index into the audio_sample_rates[] etc. vectors
* It is guaranteed that AudioStatus.num_sources == 0
*/
bool audio_set_sample_rate(int index)
{
close_audio();
audio_sample_rate_index = index;
return open_audio();
}
bool audio_set_sample_size(int index)
{
close_audio();
audio_sample_size_index = index;
return open_audio();
}
bool audio_set_channels(int index)
{
close_audio();
audio_channel_count_index = index;
return open_audio();
}
/*
* 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)
{
return main_mute;
}
uint32 audio_get_main_volume(void)
{
return 0x01000100;
}
bool audio_get_speaker_mute(void)
{
return speaker_mute;
}
uint32 audio_get_speaker_volume(void)
{
return 0x01000100;
}
void audio_set_main_mute(bool mute)
{
main_mute = mute;
}
void audio_set_main_volume(uint32 vol)
{
}
void audio_set_speaker_mute(bool mute)
{
speaker_mute = mute;
}
void audio_set_speaker_volume(uint32 vol)
{
}
static int audioInt(void)
{
SetInterruptFlag(INTFLAG_AUDIO);
TriggerInterrupt();
return 0;
}

View File

@ -1,46 +0,0 @@
/*
* autorelease.h - a macro wrapping autorelease pools for use with Objective-C++ source files.
*
* Expands to @autoreleasepool on clang, uses a little hack to emulate @autoreleasepool on gcc.
*
* (C) 2012 Charles Srstka
*
* 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
*/
#import <Foundation/Foundation.h>
#ifndef __Autorelease_H__
#define __Autorelease_H__
// just a little forward compatibility in case we ever support LLVM/clang
#if __clang__
#define AUTORELEASE_POOL @autoreleasepool
#else
class Autorelease_Pool_Wrapper {
public:
Autorelease_Pool_Wrapper() { m_pool = [[NSAutoreleasePool alloc] init]; }
~Autorelease_Pool_Wrapper() { [m_pool drain]; }
operator bool() const { return true; }
private:
NSAutoreleasePool *m_pool;
};
#define POOL_NAME(x, y) x##_##y
#define POOL_NAME2(x, y) POOL_NAME(x, y)
#define AUTORELEASE_POOL if(Autorelease_Pool_Wrapper POOL_NAME2(pool, __LINE__) = Autorelease_Pool_Wrapper())
#endif // !__clang__
#endif // __Autorelease_H__

View File

@ -1,211 +0,0 @@
/*
* clip_macosx.cpp - Clipboard handling, MacOS X (Carbon) 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"
#define _UINT64
#include <Carbon/Carbon.h>
#include "clip.h"
#include "main.h"
#include "cpu_emulation.h"
#include "emul_op.h"
#define DEBUG 0
#include "debug.h"
// Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the MacOS X side
static bool we_put_this_data = false;
static void SwapScrapData(uint32 type, void *data, int32 length, int from_host) {
#if BYTE_ORDER != BIG_ENDIAN
if (type == kScrapFlavorTypeTextStyle) {
uint16 *sdata = (uint16 *) data;
// the first short stores the number of runs
uint16 runs = sdata[0];
sdata[0] = htons(sdata[0]);
if (from_host)
runs = sdata[0];
sdata++;
// loop through each run
for (int i = 0; i < runs; i++) {
struct style_data {
uint32 offset;
uint16 line_height;
uint16 line_ascent;
uint16 font_family;
uint16 character_style; // not swapped
uint16 point_size;
uint16 red;
uint16 green;
uint16 blue;
} *style = (struct style_data *) (sdata + i*10);
style->offset = htonl(style->offset);
style->line_height = htons(style->line_height);
style->line_ascent = htons(style->line_ascent);
style->font_family = htons(style->font_family);
style->point_size = htons(style->point_size);
style->red = htons(style->red);
style->green = htons(style->green);
style->blue = htons(style->blue);
}
} else {
// add byteswapping code for other flavor types here ...
}
#endif
}
/*
* Initialization
*/
void ClipInit(void)
{
}
/*
* Deinitialization
*/
void ClipExit(void)
{
}
/*
* Mac application reads clipboard
*/
void GetScrap(void **handle, uint32 type, int32 offset)
{
#if defined(__LP64__)
D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset));
#warning Carbon scrapbook function are not implemented in 64-bit mode
#else
D(bug("GetScrap handle %p, type %08x, offset %d\n", handle, type, offset));
ScrapRef theScrap;
if (GetCurrentScrap(&theScrap) != noErr) {
D(bug(" could not open scrap\n"));
return;
}
Size byteCount;
if (GetScrapFlavorSize(theScrap, type, &byteCount) == noErr) {
// Allocate space for new scrap in MacOS side
M68kRegisters r;
r.d[0] = byteCount;
Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
uint32 scrap_area = r.a[0];
// Get the native clipboard data
if (scrap_area) {
uint8 * const data = Mac2HostAddr(scrap_area);
if (GetScrapFlavorData(theScrap, type, &byteCount, data) == noErr) {
SwapScrapData(type, data, byteCount, FALSE);
// Add new data to clipboard
static uint8 proc[] = {
0x59, 0x8f, // subq.l #4,sp
0xa9, 0xfc, // ZeroScrap()
0x2f, 0x3c, 0, 0, 0, 0, // move.l #length,-(sp)
0x2f, 0x3c, 0, 0, 0, 0, // move.l #type,-(sp)
0x2f, 0x3c, 0, 0, 0, 0, // move.l #outbuf,-(sp)
0xa9, 0xfe, // PutScrap()
0x58, 0x8f, // addq.l #4,sp
M68K_RTS >> 8, M68K_RTS & 0xff
};
r.d[0] = sizeof(proc);
Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
uint32 proc_area = r.a[0];
if (proc_area) {
Host2Mac_memcpy(proc_area, proc, sizeof(proc));
WriteMacInt32(proc_area + 6, byteCount);
WriteMacInt32(proc_area + 12, type);
WriteMacInt32(proc_area + 18, scrap_area);
we_put_this_data = true;
Execute68k(proc_area, &r);
r.a[0] = proc_area;
Execute68kTrap(0xa01f, &r); // DisposePtr
}
}
r.a[0] = scrap_area;
Execute68kTrap(0xa01f, &r); // DisposePtr
}
}
#endif
}
/*
* ZeroScrap() is called before a Mac application writes to the clipboard; clears out the previous contents
*/
void ZeroScrap()
{
D(bug("ZeroScrap\n"));
we_put_this_data = false;
}
/*
* Mac application wrote to clipboard
*/
void PutScrap(uint32 type, void *scrap, int32 length)
{
#if defined(__LP64__)
#warning Carbon scrapbook function are not implemented in 64-bit mode
D(bug("PutScrap type %4.4s, data %08lx, length %ld\n", &type, scrap, length));
#else
static bool clear = true;
D(bug("PutScrap type %4.4s, data %08lx, length %ld\n", &type, scrap, length));
ScrapRef theScrap;
if (we_put_this_data) {
we_put_this_data = false;
clear = true;
return;
}
if (length <= 0)
return;
if (clear) {
D(bug(" calling ClearCurrentScrap\n"));
ClearCurrentScrap();
}
if (GetCurrentScrap(&theScrap) != noErr) {
D(bug(" could not open scrap\n"));
return;
}
SwapScrapData(type, scrap, length, TRUE);
if (PutScrapFlavor(theScrap, type, kScrapFlavorMaskNone, length, scrap) != noErr) {
D(bug(" could not put to scrap\n"));
//return;
}
SwapScrapData(type, scrap, length, FALSE); // swap it back
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -1,634 +0,0 @@
/*
* extfs_macosx.cpp - MacOS file system for access native file system access, MacOS X 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 <sys/types.h>
#include <sys/stat.h>
#include <sys/attr.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include "sysdeps.h"
#include "prefs.h"
#include "extfs.h"
#include "extfs_defs.h"
// XXX: don't clobber with native definitions
#define noErr native_noErr
#define Point native_Point
#define Rect native_Rect
#define ProcPtr native_ProcPtr
# include <CoreFoundation/CFString.h>
#undef ProcPtr
#undef Rect
#undef Point
#undef noErr
#define DEBUG 0
#include "debug.h"
// Default Finder flags
const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
/*
* Extended attributes (Tiger+)
*/
#define USE_XATTRS g_use_xattrs
static bool g_use_xattrs = false;
#define XATTR_TEST "org.BasiliskII.TestAttr"
#define XATTR_FINFO "org.BasiliskII.FinderInfo"
#define XATTR_FXINFO "org.BasiliskII.ExtendedFinderInfo"
static bool get_xattr(const char *path, const char *name, void *value, uint32 size)
{
return syscall(SYS_getxattr, path, name, value, size, 0, 0) == size;
}
static bool set_xattr(const char *path, const char *name, const void *value, uint32 size)
{
return syscall(SYS_setxattr, path, name, value, size, 0, 0) == 0;
}
static bool remove_xattr(const char *path, const char *name)
{
return syscall(SYS_removexattr, path, name, 0) == 0;
}
static bool check_xattr(void)
{
const char *path = PrefsFindString("extfs");
if (path == NULL)
return false;
const uint32 sentinel = 0xdeadbeef;
if (!set_xattr(path, XATTR_TEST, &sentinel, sizeof(sentinel)))
return false;
uint32 v;
if (!get_xattr(path, XATTR_TEST, &v, sizeof(v)))
return false;
if (!remove_xattr(path, XATTR_TEST))
return false;
return v == sentinel;
}
/*
* Initialization
*/
void extfs_init(void)
{
g_use_xattrs = check_xattr();
}
/*
* Deinitialization
*/
void extfs_exit(void)
{
}
/*
* 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);
}
/*
* Finder info manipulation helpers
*/
typedef uint8 FinderInfo[SIZEOF_FInfo];
struct FinderInfoAttrBuf {
uint32 length;
FinderInfo finderInfo;
FinderInfo extendedFinderInfo;
};
static const FinderInfo kNativeFInfoMask = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00};
static const FinderInfo kNativeFXInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00};
static const FinderInfo kNativeDInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00};
static const FinderInfo kNativeDXInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00}; /* XXX: keep frScroll? */
static void finfo_merge(FinderInfo dst, const FinderInfo emu, const FinderInfo nat, const FinderInfo mask)
{
for (int i = 0; i < SIZEOF_FInfo; i++)
dst[i] = (emu[i] & ~mask[i]) | (nat[i] & mask[i]);
}
static void finfo_split(FinderInfo dst, const FinderInfo emu, const FinderInfo mask)
{
for (int i = 0; i < SIZEOF_FInfo; i++)
dst[i] = emu[i] & mask[i];
}
/*
* Finder info are kept in helper files (on anything below Tiger)
*
* Finder info:
* /path/.finf/file
*
* The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo
* (16+16 bytes)
*/
static void make_finf_path(const char *src, char *dest, bool only_dir = false)
{
dest[0] = 0;
// Get pointer to last component of path
const char *last_part = strrchr(src, '/');
if (last_part)
last_part++;
else
last_part = src;
// Copy everything before
strncpy(dest, src, last_part-src);
dest[last_part-src] = 0;
// Add additional component
strncat(dest, ".finf/", MAX_PATH_LENGTH-1);
// Add last component
if (!only_dir)
strncat(dest, last_part, MAX_PATH_LENGTH-1);
}
static int create_finf_dir(const char *path)
{
char finf_dir[MAX_PATH_LENGTH];
make_finf_path(path, finf_dir, true);
if (finf_dir[strlen(finf_dir) - 1] == '/') // Remove trailing "/"
finf_dir[strlen(finf_dir) - 1] = 0;
return mkdir(finf_dir, 0777);
}
static int open_finf(const char *path, int flag)
{
char finf_path[MAX_PATH_LENGTH];
make_finf_path(path, finf_path);
if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
flag |= O_CREAT;
int fd = open(finf_path, flag, 0666);
if (fd < 0) {
if (errno == ENOENT && (flag & O_CREAT)) {
// One path component was missing, probably the finf
// directory. Try to create it and re-open the file.
int ret = create_finf_dir(path);
if (ret < 0)
return ret;
fd = open(finf_path, flag, 0666);
}
}
return fd;
}
/*
* Resource forks are kept into their native location
*
* Resource fork:
* /path/file/..namedfork/rsrc
*/
static void make_rsrc_path(const char *src, char *dest)
{
int l = strlen(src);
if (l + 1 + 16 + 1 <= MAX_PATH_LENGTH)
memcpy(dest, src, l + 1);
else {
// The rsrc component is copied as is, if there is not enough
// space to add it. In that case, open() will fail gracefully
// and this is what we want.
dest[0] = '.';
dest[1] = '\0';
}
add_path_component(dest, "..namedfork/rsrc");
}
static int open_rsrc(const char *path, int flag)
{
char rsrc_path[MAX_PATH_LENGTH];
make_rsrc_path(path, rsrc_path);
return open(rsrc_path, flag);
}
/*
* Get/set finder info for file/directory 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')},
{".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')},
{".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
};
// Get emulated Finder info from metadata (Tiger+)
static bool get_finfo_from_xattr(const char *path, uint8 *finfo, uint8 *fxinfo)
{
if (!get_xattr(path, XATTR_FINFO, finfo, SIZEOF_FInfo))
return false;
if (fxinfo && !get_xattr(path, XATTR_FXINFO, fxinfo, SIZEOF_FXInfo))
return false;
return true;
}
// Get emulated Finder info from helper file
static bool get_finfo_from_helper(const char *path, uint8 *finfo, uint8 *fxinfo)
{
int fd = open_finf(path, O_RDONLY);
if (fd < 0)
return false;
ssize_t actual = read(fd, finfo, SIZEOF_FInfo);
if (fxinfo)
actual += read(fd, fxinfo, SIZEOF_FXInfo);
close(fd);
return actual == (SIZEOF_FInfo + (fxinfo ? SIZEOF_FXInfo : 0));
}
// Get native Finder info
static bool get_finfo_from_native(const char *path, uint8 *finfo, uint8 *fxinfo)
{
struct attrlist attrList;
memset(&attrList, 0, sizeof(attrList));
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.commonattr = ATTR_CMN_FNDRINFO;
FinderInfoAttrBuf attrBuf;
if (getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0) < 0)
return false;
memcpy(finfo, attrBuf.finderInfo, SIZEOF_FInfo);
if (fxinfo)
memcpy(fxinfo, attrBuf.extendedFinderInfo, SIZEOF_FXInfo);
return true;
}
static bool do_get_finfo(const char *path, bool has_fxinfo,
FinderInfo emu_finfo, FinderInfo emu_fxinfo,
FinderInfo nat_finfo, FinderInfo nat_fxinfo)
{
memset(emu_finfo, 0, SIZEOF_FInfo);
if (has_fxinfo)
memset(emu_fxinfo, 0, SIZEOF_FXInfo);
*((uint16 *)(emu_finfo + fdFlags)) = htonl(DEFAULT_FINDER_FLAGS);
*((uint32 *)(emu_finfo + fdLocation)) = htonl((uint32)-1);
if (USE_XATTRS)
get_finfo_from_xattr(path, emu_finfo, has_fxinfo ? emu_fxinfo : NULL);
else
get_finfo_from_helper(path, emu_finfo, has_fxinfo ? emu_fxinfo : NULL);
if (!get_finfo_from_native(path, nat_finfo, has_fxinfo ? nat_fxinfo : NULL))
return false;
return true;
}
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);
// Merge emulated and native Finder info
FinderInfo emu_finfo, emu_fxinfo;
FinderInfo nat_finfo, nat_fxinfo;
if (do_get_finfo(path, fxinfo, emu_finfo, emu_fxinfo, nat_finfo, nat_fxinfo)) {
if (!is_dir) {
finfo_merge(Mac2HostAddr(finfo), emu_finfo, nat_finfo, kNativeFInfoMask);
if (fxinfo)
finfo_merge(Mac2HostAddr(fxinfo), emu_fxinfo, nat_fxinfo, kNativeFXInfoMask);
if (ReadMacInt32(finfo + fdType) != 0 && ReadMacInt32(finfo + fdCreator) != 0)
return;
}
else {
finfo_merge(Mac2HostAddr(finfo), emu_finfo, nat_finfo, kNativeDInfoMask);
if (fxinfo)
finfo_merge(Mac2HostAddr(fxinfo), emu_fxinfo, nat_fxinfo, kNativeDXInfoMask);
return;
}
}
// No native Finder info, 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 (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) {
WriteMacInt32(finfo + fdType, e2t_translation[i].type);
WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator);
break;
}
}
}
}
// Set emulated Finder info into metada (Tiger+)
static bool set_finfo_to_xattr(const char *path, const uint8 *finfo, const uint8 *fxinfo)
{
if (!set_xattr(path, XATTR_FINFO, finfo, SIZEOF_FInfo))
return false;
if (fxinfo && !set_xattr(path, XATTR_FXINFO, fxinfo, SIZEOF_FXInfo))
return false;
return true;
}
// Set emulated Finder info into helper file
static bool set_finfo_to_helper(const char *path, const uint8 *finfo, const uint8 *fxinfo)
{
int fd = open_finf(path, O_RDWR);
if (fd < 0)
return false;
ssize_t actual = write(fd, finfo, SIZEOF_FInfo);
if (fxinfo)
actual += write(fd, fxinfo, SIZEOF_FXInfo);
close(fd);
return actual == (SIZEOF_FInfo + (fxinfo ? SIZEOF_FXInfo : 0));
}
// Set native Finder info
static bool set_finfo_to_native(const char *path, const uint8 *finfo, const uint8 *fxinfo, bool is_dir)
{
struct attrlist attrList;
memset(&attrList, 0, sizeof(attrList));
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.commonattr = ATTR_CMN_FNDRINFO;
FinderInfoAttrBuf attrBuf;
if (getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0) < 0)
return false;
finfo_merge(attrBuf.finderInfo, attrBuf.finderInfo, finfo, is_dir ? kNativeDInfoMask : kNativeFInfoMask);
if (fxinfo)
finfo_merge(attrBuf.extendedFinderInfo, attrBuf.extendedFinderInfo, fxinfo, is_dir ? kNativeDXInfoMask : kNativeFXInfoMask);
attrList.commonattr = ATTR_CMN_FNDRINFO;
if (setattrlist(path, &attrList, attrBuf.finderInfo, 2 * SIZEOF_FInfo, 0) < 0)
return false;
return true;
}
void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
{
// Extract native Finder info flags
FinderInfo nat_finfo, nat_fxinfo;
const uint8 *emu_finfo = Mac2HostAddr(finfo);
const uint8 *emu_fxinfo = fxinfo ? Mac2HostAddr(fxinfo) : NULL;
finfo_split(nat_finfo, emu_finfo, is_dir ? kNativeDInfoMask : kNativeFInfoMask);
if (fxinfo)
finfo_split(nat_fxinfo, emu_fxinfo, is_dir ? kNativeDXInfoMask : kNativeFXInfoMask);
// Update Finder info file (all flags)
if (USE_XATTRS)
set_finfo_to_xattr(path, emu_finfo, emu_fxinfo);
else
set_finfo_to_helper(path, emu_finfo, emu_fxinfo);
// Update native Finder info flags
set_finfo_to_native(path, nat_finfo, nat_fxinfo, is_dir);
}
/*
* 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_finf_path(path, helper_path, false);
remove(helper_path);
make_rsrc_path(path, helper_path);
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);
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_finf_path(old_path, old_helper_path, false);
make_finf_path(new_path, new_helper_path, false);
create_finf_dir(new_path);
rename(old_helper_path, new_helper_path);
make_rsrc_path(old_path, old_helper_path);
make_rsrc_path(new_path, new_helper_path);
rename(old_helper_path, new_helper_path);
// Now rename file
return rename(old_path, new_path) == 0;
}
/*
* Strings (filenames) conversion
*/
// Convert string in the specified source and target encodings
const char *convert_string(const char *str, CFStringEncoding from, CFStringEncoding to)
{
const char *ostr = str;
CFStringRef cfstr = CFStringCreateWithCString(NULL, str, from);
if (cfstr) {
static char buffer[MAX_PATH_LENGTH];
memset(buffer, 0, sizeof(buffer));
if (CFStringGetCString(cfstr, buffer, sizeof(buffer), to))
ostr = buffer;
CFRelease(cfstr);
}
return ostr;
}
// Convert from the host OS filename encoding to MacRoman
const char *host_encoding_to_macroman(const char *filename)
{
return convert_string(filename, kCFStringEncodingUTF8, kCFStringEncodingMacRoman);
}
// Convert from MacRoman to host OS filename encoding
const char *macroman_to_host_encoding(const char *filename)
{
return convert_string(filename, kCFStringEncodingMacRoman, kCFStringEncodingUTF8);
}

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