- AmigaOS bug fixes by J.Lachmann (floppy, 2060scsi.device, "Add Volume" in

prefs editor)
- imported some changes from the Windows source (1Hz interrupt, FPU fixes)
This commit is contained in:
cebix 2000-07-14 21:29:16 +00:00
parent 8ae2a2d66c
commit de3164ecc0
18 changed files with 457 additions and 254 deletions

View File

@ -1,4 +1,13 @@
V0.8 (snapshot) -
- AmigaOS: enabled floppy support, fixed floppy bugs [Jürgen Lachmann]
- AmigaOS/sys_amiga.cpp: workaround for 2060scsi.device bug when
when reading from CD-ROM [Jürgen Lachmann]
- AmigaOS/prefs_editor_amiga.cpp: fixed bug when adding volumes
[Jürgen Lachmann]
- Imported some changes from the Windows port, most notably FPU fixes
and the 1Hz interrupt [Lauri Pesonen]
V0.8 (snapshot) - 13.Jul.2000
- Unix: runs natively on NetBSD/m68k
- Unix: compiles without pthreads, but without serial/ethernet/audio
support

View File

@ -347,6 +347,13 @@ void __saveds quit_emulator(void)
void QuitEmulator(void)
{
// Stop 60Hz thread
if (tick_proc) {
SetSignal(0, SIGF_SINGLE);
tick_proc_active = false;
Wait(SIGF_SINGLE);
}
// Restore stack
if (stack_swapped) {
stack_swapped = false;
@ -360,13 +367,6 @@ void QuitEmulator(void)
FreeSignal(IRQSig);
}
// Stop 60Hz thread
if (tick_proc) {
SetSignal(0, SIGF_SINGLE);
tick_proc_active = false;
Wait(SIGF_SINGLE);
}
// Remove trap handler
MainTask->tc_TrapCode = OldTrapHandler;
@ -495,6 +495,8 @@ static __saveds void tick_func(void)
if (++tick_counter > 60) {
tick_counter = 0;
WriteMacInt32(0x20c, TimerDateTime());
SetInterruptFlag(INTFLAG_1HZ);
TriggerInterrupt();
}
// Trigger 60Hz interrupt

View File

@ -513,6 +513,9 @@ quit:
FreeAslRequest(dev_request);
FreeAslRequest(file_request);
// Delete menus
LT_DisposeMenu(menu);
// Delete handle
LT_DeleteHandle(h);
@ -873,9 +876,6 @@ do_req: if (req) {
}
} while (!done);
// Delete handle
LT_DeleteHandle(h);
// Update preferences and list view
if (ok_clicked) {
char str[256];
@ -913,6 +913,9 @@ do_req: if (req) {
LT_SetAttributes(h2, GAD_DISK_LIST, GTLV_Labels, (ULONG)&disk_list, TAG_END);
ghost_volumes_gadgets(h2);
}
// Delete handle
LT_DeleteHandle(h);
}
// Remove volume from list

View File

@ -52,6 +52,8 @@ struct file_handle {
ULONG block_size; // Block size of device (must be a power of two)
bool is_nsd; // New style device?
bool does_64bit; // Supports 64 bit trackdisk commands?
bool is_ejected; // Volume has been (logically) ejected
bool is_2060scsi; // Enable workaround for 2060scsi.device CD-ROM TD_READ bug
};
@ -89,10 +91,14 @@ void SysInit(void)
void SysExit(void)
{
// Delete port and temporary buffer
if (the_port)
if (the_port) {
DeleteMsgPort(the_port);
if (tmp_buf)
the_port = NULL;
}
if (tmp_buf) {
FreeMem(tmp_buf, TMP_BUF_SIZE);
tmp_buf = NULL;
}
}
@ -103,16 +109,14 @@ void SysExit(void)
void SysAddFloppyPrefs(void)
{
#if 0
for (int i=0; i<4; i++) {
ULONG id = GetUnitID(i);
if (id == DRT_150RPM) { // We need an HD drive
char str[256];
sprintf(str, "/dev/mfm.device/%d/0/0/1474560/512", i);
sprintf(str, "/dev/mfm.device/%d/0/0/2880/512", i);
PrefsAddString("floppy", str);
}
}
#endif
}
@ -257,6 +261,8 @@ void *Sys_open(const char *name, bool read_only)
fh->block_size = dev_bsize;
fh->is_nsd = is_nsd;
fh->does_64bit = does_64bit;
fh->is_ejected = false;
fh->is_2060scsi = (strcmp(dev_name, "2060scsi.device") == 0);
return fh;
}
}
@ -313,9 +319,72 @@ static loff_t send_io_request(file_handle *fh, bool writing, ULONG length, loff_
fh->io->io_Length = length;
fh->io->io_Offset = offset;
fh->io->io_Data = data;
if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != length)
return 0;
return fh->io->io_Actual;
if (fh->is_2060scsi && fh->block_size == 2048) {
// 2060scsi.device has serious problems reading CD-ROMs via TD_READ
static struct SCSICmd scsi;
const int SENSE_LENGTH = 256;
static UBYTE sense_buffer[SENSE_LENGTH]; // Buffer for autosense data
static UBYTE cmd_buffer[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
D(bug("send_io_request length=%lu offset=%lu\n", length, (ULONG) offset));
memset(sense_buffer, 0, sizeof(sense_buffer));
scsi.scsi_Command = cmd_buffer;
scsi.scsi_CmdLength = sizeof(cmd_buffer);
scsi.scsi_SenseData = sense_buffer;
scsi.scsi_SenseLength = SENSE_LENGTH;
scsi.scsi_Flags = SCSIF_AUTOSENSE | (writing ? SCSIF_WRITE : SCSIF_READ);
scsi.scsi_Data = (UWORD *) data;
scsi.scsi_Length = length;
ULONG block_offset = (ULONG) offset / fh->block_size;
ULONG block_length = length / fh->block_size;
cmd_buffer[2] = block_offset >> 24;
cmd_buffer[3] = block_offset >> 16;
cmd_buffer[4] = block_offset >> 8;
cmd_buffer[5] = block_offset & 0xff;
cmd_buffer[7] = block_length >> 8;
cmd_buffer[8] = block_length & 0xff;
fh->io->io_Command = HD_SCSICMD;
fh->io->io_Actual = 0;
fh->io->io_Offset = 0;
fh->io->io_Data = &scsi;
fh->io->io_Length = sizeof(scsi);
BYTE result = DoIO((struct IORequest *)fh->io);
if (result) {
D(bug("send_io_request SCSI FAIL result=%lu\n", result));
if (result == HFERR_BadStatus) {
D(bug("send_io_request SCSI Status=%lu\n", scsi.scsi_Status));
if (scsi.scsi_Status == 2) {
D(bug("send_io_request Sense Key=%02lx\n", sense_buffer[2] & 0x0f));
D(bug("send_io_request ASC=%02lx ASCQ=%02lx\n", sense_buffer[12], sense_buffer[13]));
}
}
return 0;
}
D(bug("send_io_request SCSI Actual=%lu\n", scsi.scsi_Actual));
if (scsi.scsi_Actual != length)
return 0;
return scsi.scsi_Actual;
} else {
if (DoIO((struct IORequest *)fh->io) || fh->io->io_Actual != length)
return 0;
return fh->io->io_Actual;
}
}
@ -528,6 +597,8 @@ void SysEject(void *arg)
fh->io->io_Command = TD_EJECT;
fh->io->io_Length = 1;
DoIO((struct IORequest *)fh->io);
fh->is_ejected = true;
}
}
@ -565,9 +636,8 @@ bool SysIsReadOnly(void *arg)
} else {
// Device, check write protection
fh->io->io_Flags = IOF_QUICK;
fh->io->io_Command = TD_PROTSTATUS;
BeginIO((struct IORequest *)fh->io);
DoIO((struct IORequest *)fh->io);
if (fh->io->io_Actual)
return true;
else
@ -605,11 +675,22 @@ bool SysIsDiskInserted(void *arg)
else {
// Check medium status
fh->io->io_Flags = IOF_QUICK;
fh->io->io_Command = TD_CHANGESTATE;
fh->io->io_Actual = 0;
BeginIO((struct IORequest *)fh->io);
return fh->io->io_Actual == 0;
DoIO((struct IORequest *)fh->io);
bool inserted = (fh->io->io_Actual == 0);
if (!inserted) {
// Disk was ejected and has now been taken out
fh->is_ejected = false;
}
if (fh->is_ejected) {
// Disk was ejected but has not yet been taken out, report it as
// no longer in the drive
return false;
} else
return inserted;
}
}

View File

@ -47,7 +47,8 @@
enum {
DISPLAY_WINDOW,
DISPLAY_PIP,
DISPLAY_SCREEN
DISPLAY_SCREEN_P96,
DISPLAY_SCREEN_CGFX
};
// Global variables
@ -58,8 +59,6 @@ static struct Window *the_win = NULL;
static struct BitMap *the_bitmap = NULL;
static LONG black_pen = -1, white_pen = -1;
static struct Process *periodic_proc = NULL; // Periodic process
static bool is_cgfx = false; // Flag: screen mode is a CyberGfx mode
static bool is_p96 = false; // Flag: screen mode is a Picasso96 mode
extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp)
@ -186,33 +185,15 @@ static bool init_pip(int width, int height)
return true;
}
// Open screen (requires Picasso96/CyberGfx as we need chunky modes)
static bool init_screen(ULONG mode_id)
// Open Picasso96 screen
static bool init_screen_p96(ULONG mode_id)
{
// Set relative mouse mode
ADBSetRelMouseMode(true);
// Check whether the mode is a Picasso96 mode or a CyberGfx mode
if (P96Base && p96GetModeIDAttr(mode_id, P96IDA_ISP96))
is_p96 = true;
else if (CyberGfxBase && IsCyberModeID(mode_id))
is_cgfx = true;
else {
ErrorAlert(GetString(STR_NO_P96_MODE_ERR));
return false;
}
uint32 depth;
uint32 format;
// Check if the mode is one we can handle
if (is_p96) {
depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT);
} else {
depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id);
}
uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
uint32 format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT);
switch (depth) {
case 8:
@ -220,7 +201,7 @@ static bool init_screen(ULONG mode_id)
break;
case 15:
case 16:
if (format != RGBFB_R5G5B5 && format != PIXFMT_RGB16) {
if (format != RGBFB_R5G5B5) {
ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
return false;
}
@ -228,7 +209,7 @@ static bool init_screen(ULONG mode_id)
break;
case 24:
case 32:
if (format != RGBFB_A8R8G8B8 && format != PIXFMT_ARGB32) {
if (format != RGBFB_A8R8G8B8) {
ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
return false;
}
@ -240,40 +221,22 @@ static bool init_screen(ULONG mode_id)
}
// Yes, get width and height
uint32 width;
uint32 height;
uint32 width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH);
uint32 height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT);
if (is_p96) {
width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH);
height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT);
} else {
width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id);
height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id);
}
VideoMonitor.x = width;
VideoMonitor.y = height;
// Open screen
if (is_p96) {
the_screen = p96OpenScreenTags(
P96SA_DisplayID, mode_id,
P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
P96SA_Quiet, TRUE,
P96SA_NoMemory, TRUE,
P96SA_NoSprite, TRUE,
P96SA_Exclusive, TRUE,
TAG_END
);
} else {
the_screen = OpenScreenTags(NULL,
SA_DisplayID, mode_id,
SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
SA_Quiet, TRUE,
SA_Exclusive, TRUE,
TAG_END
);
}
the_screen = p96OpenScreenTags(
P96SA_DisplayID, mode_id,
P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
P96SA_Quiet, TRUE,
P96SA_NoMemory, TRUE,
P96SA_NoSprite, TRUE,
P96SA_Exclusive, TRUE,
TAG_END
);
if (the_screen == NULL) {
ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
return false;
@ -298,19 +261,92 @@ static bool init_screen(ULONG mode_id)
// Set VideoMonitor
ScreenToFront(the_screen);
if (is_p96) {
VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY);
VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_BYTESPERROW);
} else {
static UWORD ptr[] = { 0, 0, 0, 0 };
SetPointer(the_win, ptr, 0, 0, 0, 0); // Hide Pointer
VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY);
VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_BYTESPERROW);
return true;
}
APTR handle = LockBitMapTags(the_screen->RastPort.BitMap,
LBMI_BASEADDRESS, (ULONG)&VideoMonitor.mac_frame_base,
TAG_END);
UnLockBitMap(handle);
VideoMonitor.bytes_per_row = GetCyberMapAttr(the_screen->RastPort.BitMap, CYBRMATTR_XMOD);
// Open CyberGraphX screen
static bool init_screen_cgfx(ULONG mode_id)
{
// Set relative mouse mode
ADBSetRelMouseMode(true);
// Check if the mode is one we can handle
uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
uint32 format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id);
switch (depth) {
case 8:
VideoMonitor.mode = VMODE_8BIT;
break;
case 15:
case 16:
if (format != PIXFMT_RGB16) {
ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
return false;
}
VideoMonitor.mode = VMODE_16BIT;
break;
case 24:
case 32:
if (format != PIXFMT_ARGB32) {
ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
return false;
}
VideoMonitor.mode = VMODE_32BIT;
break;
default:
ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
return false;
}
// Yes, get width and height
uint32 width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id);
uint32 height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id);
VideoMonitor.x = width;
VideoMonitor.y = height;
// Open screen
the_screen = OpenScreenTags(NULL,
SA_DisplayID, mode_id,
SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
SA_Quiet, TRUE,
SA_Exclusive, TRUE,
TAG_END
);
if (the_screen == NULL) {
ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
return false;
}
// Open window
the_win = OpenWindowTags(NULL,
WA_Left, 0, WA_Top, 0,
WA_Width, width, WA_Height, height,
WA_NoCareRefresh, TRUE,
WA_Borderless, TRUE,
WA_Activate, TRUE,
WA_RMBTrap, TRUE,
WA_ReportMouse, TRUE,
WA_CustomScreen, (ULONG)the_screen,
TAG_END
);
if (the_win == NULL) {
ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
return false;
}
// Set VideoMonitor
ScreenToFront(the_screen);
static UWORD ptr[] = { 0, 0, 0, 0 };
SetPointer(the_win, ptr, 0, 0, 0, 0); // Hide mouse pointer
APTR handle = LockBitMapTags(the_screen->RastPort.BitMap,
LBMI_BASEADDRESS, (ULONG)&VideoMonitor.mac_frame_base,
TAG_END);
UnLockBitMap(handle);
VideoMonitor.bytes_per_row = GetCyberMapAttr(the_screen->RastPort.BitMap, CYBRMATTR_XMOD);
return true;
}
@ -337,8 +373,16 @@ bool VideoInit(bool classic)
display_type = DISPLAY_WINDOW;
else if (sscanf(mode_str, "pip/%d/%d", &width, &height) == 2 && P96Base)
display_type = DISPLAY_PIP;
else if (sscanf(mode_str, "scr/%08lx", &mode_id) == 1 && (CyberGfxBase || P96Base))
display_type = DISPLAY_SCREEN;
else if (sscanf(mode_str, "scr/%08lx", &mode_id) == 1 && (CyberGfxBase || P96Base)) {
if (P96Base && p96GetModeIDAttr(mode_id, P96IDA_ISP96))
display_type = DISPLAY_SCREEN_P96;
else if (CyberGfxBase && IsCyberModeID(mode_id))
display_type = DISPLAY_SCREEN_CGFX;
else {
ErrorAlert(GetString(STR_NO_P96_MODE_ERR));
return false;
}
}
}
// Open display
@ -353,8 +397,13 @@ bool VideoInit(bool classic)
return false;
break;
case DISPLAY_SCREEN:
if (!init_screen(mode_id))
case DISPLAY_SCREEN_P96:
if (!init_screen_p96(mode_id))
return false;
break;
case DISPLAY_SCREEN_CGFX:
if (!init_screen_cgfx(mode_id))
return false;
break;
}
@ -413,7 +462,7 @@ void VideoExit(void)
p96PIP_Close(the_win);
break;
case DISPLAY_SCREEN:
case DISPLAY_SCREEN_P96:
// Close window
if (the_win)
@ -421,11 +470,20 @@ void VideoExit(void)
// Close screen
if (the_screen) {
if (is_p96)
p96CloseScreen(the_screen);
else
CloseScreen(the_screen);
p96CloseScreen(the_screen);
the_screen = NULL;
}
break;
case DISPLAY_SCREEN_CGFX:
// Close window
if (the_win)
CloseWindow(the_win);
// Close screen
if (the_screen) {
CloseScreen(the_screen);
the_screen = NULL;
}
break;
@ -439,7 +497,7 @@ void VideoExit(void)
void video_set_palette(uint8 *pal)
{
if (display_type == DISPLAY_SCREEN) {
if (display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) {
// Convert palette to 32 bits
ULONG table[2 + 256 * 3];
@ -482,7 +540,7 @@ static __saveds void periodic_func(void)
if (win_port) {
win_mask = 1 << win_port->mp_SigBit;
the_win->UserPort = win_port;
ModifyIDCMP(the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | (display_type == DISPLAY_SCREEN ? IDCMP_DELTAMOVE : 0));
ModifyIDCMP(the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | ((display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) ? IDCMP_DELTAMOVE : 0));
}
// Start 60Hz timer for window refresh
@ -540,7 +598,7 @@ static __saveds void periodic_func(void)
// Handle message according to class
switch (cl) {
case IDCMP_MOUSEMOVE:
if (display_type == DISPLAY_SCREEN)
if (display_type == DISPLAY_SCREEN || display_type == DISPLAY_SCREEN_CGFX)
ADBMouseMoved(mx, my);
else
ADBMouseMoved(mx - the_win->BorderLeft, my - the_win->BorderTop);

View File

@ -503,6 +503,8 @@ status_t BasiliskII::tick_func(void *arg)
if (++tick_counter > 60) {
tick_counter = 0;
WriteMacInt32(0x20c, TimerDateTime());
SetInterruptFlag(INTFLAG_1HZ);
TriggerInterrupt();
}
// Trigger 60Hz interrupt

View File

@ -708,6 +708,9 @@ static void one_second(void)
// Pseudo Mac 1Hz interrupt, update local time
WriteMacInt32(0x20c, TimerDateTime());
SetInterruptFlag(INTFLAG_60HZ);
TriggerInterrupt();
#ifndef HAVE_PTHREADS
static int second_counter = 0;
if (++second_counter > 60) {

View File

@ -151,9 +151,6 @@ static DriveInfo *first_drive_info;
// Icon address (Mac address space, set by PatchROM())
uint32 CDROMIconAddr;
// Number of ticks between checks for disk insertion
const int driver_delay = 120;
// Flag: Control(accRun) has been called, interrupt routine is now active
static bool acc_run_called = false;
@ -964,18 +961,13 @@ int16 CDROMStatus(uint32 pb, uint32 dce)
/*
* Driver interrupt routine - check for volumes to be mounted
* Driver interrupt routine (1Hz) - check for volumes to be mounted
*/
void CDROMInterrupt(void)
{
static int tick_count = 0;
if (!acc_run_called)
return;
tick_count++;
if (tick_count > driver_delay) {
tick_count = 0;
mount_mountable_volumes();
}
mount_mountable_volumes();
}

View File

@ -90,9 +90,6 @@ static DriveInfo *first_drive_info;
// Icon address (Mac address space, set by PatchROM())
uint32 DiskIconAddr;
// Number of ticks between checks for disk insertion
const int driver_delay = 120;
// Flag: Control(accRun) has been called, interrupt routine is now active
static bool acc_run_called = false;
@ -495,18 +492,13 @@ int16 DiskStatus(uint32 pb, uint32 dce)
/*
* Driver interrupt routine - check for volumes to be mounted
* Driver interrupt routine (1Hz) - check for volumes to be mounted
*/
void DiskInterrupt(void)
{
static int tick_count = 0;
if (!acc_run_called)
return;
tick_count++;
if (tick_count > driver_delay) {
tick_count = 0;
mount_mountable_volumes();
}
mount_mountable_volumes();
}

View File

@ -413,6 +413,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
case M68K_EMUL_OP_IRQ: // Level 1 interrupt
r->d[0] = 0;
if (InterruptFlags & INTFLAG_60HZ) {
ClearInterruptFlag(INTFLAG_60HZ);
if (HasMacStarted()) {
@ -421,9 +422,6 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
ADBInterrupt();
TimerInterrupt();
VideoInterrupt();
SonyInterrupt();
DiskInterrupt();
CDROMInterrupt();
// Call DoVBLTask(0)
if (ROMVersion == ROM_VERSION_32) {
@ -435,14 +433,27 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc.
}
}
if (InterruptFlags & INTFLAG_1HZ) {
ClearInterruptFlag(INTFLAG_1HZ);
if (HasMacStarted()) {
SonyInterrupt();
DiskInterrupt();
CDROMInterrupt();
}
}
if (InterruptFlags & INTFLAG_SERIAL) {
ClearInterruptFlag(INTFLAG_SERIAL);
SerialInterrupt();
}
if (InterruptFlags & INTFLAG_ETHER) {
ClearInterruptFlag(INTFLAG_ETHER);
EtherInterrupt();
}
if (InterruptFlags & INTFLAG_AUDIO) {
ClearInterruptFlag(INTFLAG_AUDIO);
AudioInterrupt();

View File

@ -40,11 +40,14 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#ifndef WIN32
#include <unistd.h>
#include <dirent.h>
#endif
#include "cpu_emulation.h"
#include "macos_util.h"
#include "emul_op.h"
@ -55,6 +58,10 @@
#include "extfs.h"
#include "extfs_defs.h"
#ifdef WIN32
# include "posix_emu.h"
#endif
#define DEBUG 0
#include "debug.h"
@ -111,6 +118,11 @@ const uint32 ROOT_PARENT_ID = 1;
// File system stack size
const int STACK_SIZE = 0x10000;
// Allocation block and clump size as reported to MacOS (these are of course
// not the real values and have no meaning on the host OS)
const int ALBLK_SIZE = 0x4000;
const int CLUMP_SIZE = 0x4000;
// Drive number of our pseudo-drive
static int drive_number;
@ -257,6 +269,8 @@ static void cstr2pstr(char *dst, const char *src)
*dst++ = strlen(src);
char c;
while ((c = *src++) != 0) {
// Note: we are converting host ':' characters to Mac '/' characters here
// '/' is not a path separator as this function is only used on object names
if (c == ':')
c = '/';
*dst++ = c;
@ -269,6 +283,8 @@ static void pstr2cstr(char *dst, const char *src)
int size = *src++;
while (size--) {
char c = *src++;
// Note: we are converting Mac '/' characters to host ':' characters here
// '/' is not a path separator as this function is only used on object names
if (c == '/')
c = ':';
*dst++ = c;
@ -281,6 +297,8 @@ static void strn2cstr(char *dst, const char *src, int size)
{
while (size--) {
char c = *src++;
// Note: we are converting Mac '/' characters to host ':' characters here
// '/' is not a path separator as this function is only used on object names
if (c == '/')
c = ':';
*dst++ = c;
@ -356,6 +374,7 @@ void ExtFSInit(void)
p->parent_id = ROOT_PARENT_ID;
p->parent = first_fs_item;
strncpy(p->name, GetString(STR_EXTFS_VOLUME_NAME), 32);
p->name[31] = 0;
// Find path for root
if ((RootPath = PrefsFindString("extfs")) != NULL) {
@ -731,7 +750,7 @@ static int16 get_current_dir(uint32 pb, uint32 dirID, uint32 &current_dir, bool
int16 vRefNum = ReadMacInt16(fs_data + fsReturn + 4);
uint32 vcb = ReadMacInt32(fs_data + fsReturn + 6);
D(bug(" UTDetermineVol() returned %d, status %d\n", r.d[0], status));
result = r.d[0] & 0xffff;
result = (int16)(r.d[0] & 0xffff);
if (result == noErr) {
switch (status) {
@ -756,7 +775,7 @@ static int16 get_current_dir(uint32 pb, uint32 dirID, uint32 &current_dir, bool
Execute68k(fs_data + fsResolveWDCB, &r);
uint32 wdcb = ReadMacInt32(fs_data + fsReturn);
D(bug(" UTResolveWDCB() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdcb + wdDirID)));
result = r.d[0] & 0xffff;
result = (int16)(r.d[0] & 0xffff);
if (result == noErr)
current_dir = ReadMacInt32(wdcb + wdDirID);
}
@ -772,7 +791,7 @@ static int16 get_current_dir(uint32 pb, uint32 dirID, uint32 &current_dir, bool
r.a[0] = wdpb;
Execute68k(fs_data + fsGetDefaultVol, &r);
D(bug(" UTGetDefaultVol() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdpb + ioWDDirID)));
result = r.d[0] & 0xffff;
result = (int16)(r.d[0] & 0xffff);
if (result == noErr)
current_dir = ReadMacInt32(wdpb + ioWDDirID);
}
@ -798,7 +817,7 @@ static int16 get_path_component_name(uint32 rec)
r.a[0] = rec;
Execute68k(fs_data + fsGetPathComponentName, &r);
// D(bug(" UTGetPathComponentName returned %d\n", r.d[0]));
return r.d[0] & 0xffff;
return (int16)(r.d[0] & 0xffff);
}
@ -834,7 +853,7 @@ static int16 get_item_and_path(uint32 pb, uint32 dirID, FSItem *&item, bool no_v
r.a[1] = ReadMacInt32(parseRec + ppNamePtr);
Execute68k(fs_data + fsParsePathname, &r);
D(bug(" UTParsePathname() returned %d, startOffset %d\n", r.d[0], ReadMacInt16(parseRec + ppStartOffset)));
result = r.d[0] & 0xffff;
result = (int16)(r.d[0] & 0xffff);
if (result == noErr) {
// Check for leading delimiter of the partial pathname
@ -968,11 +987,11 @@ static int16 fs_volume_mount(uint32 pb)
uint32 vcb = ReadMacInt32(fs_data + fsReturn + 2);
D(bug(" UTAllocateVCB() returned %d, vcb %08lx, size %d\n", r.d[0], vcb, sysVCBLength));
if (r.d[0] & 0xffff)
return r.d[0];
return (int16)r.d[0];
// Init VCB
WriteMacInt16(vcb + vcbSigWord, 0x4244);
#ifdef __BEOS__
#if defined(__BEOS__) || defined(WIN32)
WriteMacInt32(vcb + vcbCrDate, root_stat.st_crtime + TIME_OFFSET);
#else
WriteMacInt32(vcb + vcbCrDate, 0);
@ -982,8 +1001,8 @@ static int16 fs_volume_mount(uint32 pb)
WriteMacInt16(vcb + vcbNmFls, 1); //!!
WriteMacInt16(vcb + vcbNmRtDirs, 1); //!!
WriteMacInt16(vcb + vcbNmAlBlks, 0xffff); //!!
WriteMacInt32(vcb + vcbAlBlkSiz, 1024);
WriteMacInt32(vcb + vcbClpSiz, 1024);
WriteMacInt32(vcb + vcbAlBlkSiz, AL_BLK_SIZE);
WriteMacInt32(vcb + vcbClpSiz, CLUMPSIZE);
WriteMacInt32(vcb + vcbNxtCNID, next_cnid);
WriteMacInt16(vcb + vcbFreeBks, 0xffff); //!!
Host2Mac_memcpy(vcb + vcbVN, VOLUME_NAME, 28);
@ -997,10 +1016,10 @@ static int16 fs_volume_mount(uint32 pb)
r.a[0] = fs_data + fsReturn;
r.a[1] = vcb;
Execute68k(fs_data + fsAddNewVCB, &r);
int16 vRefNum = ReadMacInt32(fs_data + fsReturn);
int16 vRefNum = (int16)ReadMacInt32(fs_data + fsReturn);
D(bug(" UTAddNewVCB() returned %d, vRefNum %d\n", r.d[0], vRefNum));
if (r.d[0] & 0xffff)
return r.d[0];
return (int16)r.d[0];
// Post diskInsertEvent
D(bug(" posting diskInsertEvent\n"));
@ -1024,7 +1043,7 @@ static int16 fs_unmount_vol(uint32 vcb)
r.a[0] = vcb;
Execute68k(fs_data + fsDisposeVCB, &r);
D(bug(" UTDisposeVCB() returned %d\n", r.d[0]));
return r.d[0];
return (int16)r.d[0];
}
// Get information about a volume (HVolumeParam)
@ -1035,7 +1054,7 @@ static int16 fs_get_vol_info(uint32 pb, bool hfs)
// Fill in struct
if (ReadMacInt32(pb + ioNamePtr))
pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), VOLUME_NAME);
#ifdef __BEOS__
#if defined(__BEOS__) || defined(WIN32)
WriteMacInt32(pb + ioVCrDate, root_stat.st_crtime + TIME_OFFSET);
#else
WriteMacInt32(pb + ioVCrDate, 0);
@ -1046,8 +1065,8 @@ static int16 fs_get_vol_info(uint32 pb, bool hfs)
WriteMacInt16(pb + ioVBitMap, 0);
WriteMacInt16(pb + ioAllocPtr, 0);
WriteMacInt16(pb + ioVNmAlBlks, 0xffff); //!!
WriteMacInt32(pb + ioVAlBlkSiz, 1024);
WriteMacInt32(pb + ioVClpSiz, 1024);
WriteMacInt32(pb + ioVAlBlkSiz, AL_BLK_SIZE);
WriteMacInt32(pb + ioVClpSiz, CLUMP_SIZE);
WriteMacInt16(pb + ioAlBlSt, 0);
WriteMacInt32(pb + ioVNxtCNID, next_cnid);
WriteMacInt16(pb + ioVFrBlk, 0xffff); //!!
@ -1105,7 +1124,7 @@ static int16 fs_get_vol(uint32 pb)
r.a[0] = pb;
Execute68k(fs_data + fsGetDefaultVol, &r);
D(bug(" UTGetDefaultVol() returned %d\n", r.d[0]));
return r.d[0];
return (int16)r.d[0];
}
// Set default volume (WDParam)
@ -1161,7 +1180,7 @@ static int16 fs_set_vol(uint32 pb, bool hfs, uint32 vcb)
r.d[2] = refNum;
Execute68k(fs_data + fsSetDefaultVol, &r);
D(bug(" UTSetDefaultVol() returned %d\n", r.d[0]));
return r.d[0];
return (int16)r.d[0];
}
// Query file attributes (HFileParam)
@ -1227,7 +1246,7 @@ read_next_de:
WriteMacInt8(pb + ioFlAttrib, access(full_path, W_OK) == 0 ? 0 : faLocked);
WriteMacInt32(pb + ioDirID, fs_item->id);
#ifdef __BEOS__
#if defined(__BEOS__) || defined(WIN32)
WriteMacInt32(pb + ioFlCrDat, st.st_crtime + TIME_OFFSET);
#else
WriteMacInt32(pb + ioFlCrDat, 0);
@ -1245,11 +1264,11 @@ read_next_de:
WriteMacInt16(pb + ioFlStBlk, 0);
WriteMacInt32(pb + ioFlLgLen, st.st_size);
WriteMacInt32(pb + ioFlPyLen, (st.st_size + 1023) & ~1023);
WriteMacInt32(pb + ioFlPyLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
WriteMacInt16(pb + ioFlRStBlk, 0);
uint32 rf_size = get_rfork_size(full_path);
WriteMacInt32(pb + ioFlRLgLen, rf_size);
WriteMacInt32(pb + ioFlRPyLen, (rf_size + 1023) & ~1023);
WriteMacInt32(pb + ioFlRPyLen, (rf_size | (AL_BLK_SIZE - 1)) + 1);
if (hfs) {
WriteMacInt32(pb + ioFlBkDat, 0);
@ -1357,7 +1376,7 @@ read_next_de:
WriteMacInt8(pb + ioACUser, 0);
WriteMacInt32(pb + ioDirID, fs_item->id);
WriteMacInt32(pb + ioFlParID, fs_item->parent_id);
#ifdef __BEOS__
#if defined(__BEOS__) || defined(WIN32)
WriteMacInt32(pb + ioFlCrDat, st.st_crtime + TIME_OFFSET);
#else
WriteMacInt32(pb + ioFlCrDat, 0);
@ -1411,11 +1430,11 @@ read_next_de:
WriteMacInt16(pb + ioFlFndrInfo + fdFlags, fflags);
WriteMacInt16(pb + ioFlStBlk, 0);
WriteMacInt32(pb + ioFlLgLen, st.st_size);
WriteMacInt32(pb + ioFlPyLen, (st.st_size + 1023) & ~1023);
WriteMacInt32(pb + ioFlPyLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
WriteMacInt16(pb + ioFlRStBlk, 0);
uint32 rf_size = get_rfork_size(full_path);
WriteMacInt32(pb + ioFlRLgLen, rf_size);
WriteMacInt32(pb + ioFlRPyLen, (rf_size + 1023) & ~1023);
WriteMacInt32(pb + ioFlRPyLen, (rf_size | (AL_BLK_SIZE - 1)) + 1);
WriteMacInt32(pb + ioFlClpSiz, 0);
}
return noErr;
@ -1438,9 +1457,9 @@ static int16 fs_set_cat_info(uint32 pb)
return errno2oserr();
// Set attributes
if (S_ISDIR(st.st_mode))
if (S_ISDIR(st.st_mode)) {
set_finder_flags(full_path, ReadMacInt16(pb + ioDrUsrWds + frFlags));
else {
} else {
set_finder_type(full_path, ReadMacInt32(pb + ioFlFndrInfo + fdType), ReadMacInt32(pb + ioFlFndrInfo + fdCreator));
set_finder_flags(full_path, ReadMacInt16(pb + ioFlFndrInfo + fdFlags));
}
@ -1490,7 +1509,7 @@ static int16 fs_open(uint32 pb, uint32 dirID, uint32 vcb, bool resource_fork)
if (access(full_path, F_OK))
return fnfErr;
fd = open_rfork(full_path, flag);
if (fd > 0) {
if (fd >= 0) {
if (fstat(fd, &st) < 0) {
close(fd);
return errno2oserr();
@ -1518,17 +1537,17 @@ static int16 fs_open(uint32 pb, uint32 dirID, uint32 vcb, bool resource_fork)
D(bug(" UTAllocateFCB() returned %d, fRefNum %d, fcb %08lx\n", r.d[0], ReadMacInt16(pb + ioRefNum), fcb));
if (r.d[0] & 0xffff) {
close(fd);
return r.d[0];
return (int16)r.d[0];
}
// Initialize FCB, fd is stored in fcbCatPos
WriteMacInt32(fcb + fcbFlNm, fs_item->id);
WriteMacInt8(fcb + fcbFlags, ((flag == O_WRONLY || flag == O_RDWR) ? fcbWriteMask : 0) | (resource_fork ? fcbResourceMask : 0) | (write_ok ? 0 : fcbFileLockedMask));
WriteMacInt32(fcb + fcbEOF, st.st_size);
WriteMacInt32(fcb + fcbPLen, (st.st_size + 1023) & ~1023);
WriteMacInt32(fcb + fcbPLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
WriteMacInt32(fcb + fcbCrPs, 0);
WriteMacInt32(fcb + fcbVPtr, vcb);
WriteMacInt32(fcb + fcbClmpSize, 1024);
WriteMacInt32(fcb + fcbClmpSize, CLUMP_SIZE);
uint32 type, creator; // BeOS: fcb may point to kernel space, but stack is switched
get_finder_type(full_path, type, creator);
WriteMacInt32(fcb + fcbFType, type);
@ -1568,7 +1587,7 @@ static int16 fs_close(uint32 pb)
r.d[0] = ReadMacInt16(pb + ioRefNum);
Execute68k(fs_data + fsReleaseFCB, &r);
D(bug(" UTReleaseFCB() returned %d\n", r.d[0]));
return r.d[0];
return (int16)r.d[0];
}
// Query information about FCB (FCBPBRec)
@ -1596,7 +1615,7 @@ static int16 fs_get_fcb_info(uint32 pb, uint32 vcb)
fcb = ReadMacInt32(fs_data + fsReturn);
D(bug(" UTIndexFCB() returned %d, fcb %p\n", r.d[0], fcb));
if (r.d[0] & 0xffff)
return r.d[0];
return (int16)r.d[0];
}
}
if (fcb == 0)
@ -1644,7 +1663,7 @@ static int16 fs_get_eof(uint32 pb)
// Adjust FCBs
WriteMacInt32(fcb + fcbEOF, st.st_size);
WriteMacInt32(fcb + fcbPLen, (st.st_size + 1023) & ~1023);
WriteMacInt32(fcb + fcbPLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
WriteMacInt32(pb + ioMisc, st.st_size);
D(bug(" adjusting FCBs\n"));
r.d[0] = ReadMacInt16(pb + ioRefNum);
@ -1679,7 +1698,7 @@ static int16 fs_set_eof(uint32 pb)
// Adjust FCBs
WriteMacInt32(fcb + fcbEOF, size);
WriteMacInt32(fcb + fcbPLen, (size + 1023) & ~1023);
WriteMacInt32(fcb + fcbPLen, (size | (AL_BLK_SIZE - 1)) + 1);
D(bug(" adjusting FCBs\n"));
r.d[0] = ReadMacInt16(pb + ioRefNum);
Execute68k(fs_data + fsAdjustEOF, &r);
@ -1764,6 +1783,10 @@ static int16 fs_read(uint32 pb)
{
D(bug(" fs_read(%08lx), refNum %d, buffer %p, count %d, posMode %d, posOffset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioBuffer), ReadMacInt32(pb + ioReqCount), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
// Check parameters
if ((int32)ReadMacInt32(pb + ioReqCount) < 0)
return paramErr;
// Find FCB and fd for file
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
if (fcb == 0)
@ -1813,6 +1836,10 @@ static int16 fs_write(uint32 pb)
{
D(bug(" fs_write(%08lx), refNum %d, buffer %p, count %d, posMode %d, posOffset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioBuffer), ReadMacInt32(pb + ioReqCount), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
// Check parameters
if ((int32)ReadMacInt32(pb + ioReqCount) < 0)
return paramErr;
// Find FCB and fd for file
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
if (fcb == 0)
@ -2023,7 +2050,7 @@ static int16 fs_open_wd(uint32 pb)
r.a[0] = pb;
Execute68k(fs_data + fsAllocateWDCB, &r);
D(bug(" UTAllocateWDCB returned %d, refNum is %d\n", r.d[0], ReadMacInt16(pb + ioVRefNum)));
return r.d[0];
return (int16)r.d[0];
}
// Close working directory (WDParam)
@ -2037,7 +2064,7 @@ static int16 fs_close_wd(uint32 pb)
r.d[0] = ReadMacInt16(pb + ioVRefNum);
Execute68k(fs_data + fsReleaseWDCB, &r);
D(bug(" UTReleaseWDCB returned %d\n", r.d[0]));
return r.d[0];
return (int16)r.d[0];
}
// Query information about working directory (WDParam)
@ -2066,7 +2093,7 @@ static int16 fs_get_wd_info(uint32 pb, uint32 vcb)
uint32 wdcb = ReadMacInt32(fs_data + fsReturn);
D(bug(" UTResolveWDCB() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdcb + wdDirID)));
if (r.d[0] & 0xffff)
return r.d[0];
return (int16)r.d[0];
// Return information
WriteMacInt32(pb + ioWDProcID, ReadMacInt32(wdcb + wdProcID));

View File

@ -26,6 +26,7 @@ const uint16 M68K_ILLEGAL = 0x4afc;
const uint16 M68K_NOP = 0x4e71;
const uint16 M68K_RTS = 0x4e75;
const uint16 M68K_RTD = 0x4e74;
const uint16 M68K_RTR = 0x4e77;
const uint16 M68K_JMP = 0x4ef9;
const uint16 M68K_JMP_A0 = 0x4ed0;
const uint16 M68K_JSR = 0x4eb9;

View File

@ -247,7 +247,12 @@ enum { // DeferredTask struct
extern void EnqueueMac(uint32 elem, uint32 list); // Enqueue QElem in list
extern int FindFreeDriveNumber(int num); // Find first free drive number, starting at "num"
extern void MountVolume(void *fh); // Mount volume with given file handle (see sys.h)
extern bool HasMacStarted(void); // Test if basic MacOS initializations are done
extern void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size); // Calculate disk image file layout given file size and first 256 data bytes
// Test if basic MacOS initializations are done
static inline bool HasMacStarted(void)
{
return ReadMacInt32(0xcfc) == 'WLSC'; // Mac warm start flag
}
#endif

View File

@ -51,11 +51,12 @@ extern bool ChoiceAlert(const char *text, const char *pos, const char *neg); //
// Interrupt flags
enum {
INTFLAG_60HZ = 1, // 60Hz VBL
INTFLAG_SERIAL = 2, // Serial driver
INTFLAG_ETHER = 4, // Ethernet driver
INTFLAG_AUDIO = 8, // Audio block read
INTFLAG_TIMER = 16 // Time Manager
INTFLAG_60HZ = 1, // 60.15Hz VBL
INTFLAG_1HZ = 2, // ~1Hz interrupt
INTFLAG_SERIAL = 4, // Serial driver
INTFLAG_ETHER = 8, // Ethernet driver
INTFLAG_AUDIO = 16, // Audio block read
INTFLAG_TIMER = 32 // Time Manager
};
extern uint32 InterruptFlags; // Currently pending interrupts

View File

@ -1,7 +1,7 @@
/*
* slot_rom.cpp - Slot declaration ROM
*
* Basilisk II (C) 1996-1997 Christian Bauer
* Basilisk II (C) 1996-2000 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

View File

@ -42,8 +42,10 @@
#define DEBUG 0
#include "debug.h"
// Check for inserted disks by polling?
#ifdef AMIGA
#define DISK_INSERT_CHECK 1 // Check for inserted disks (problem: on most hardware, disks are not ejected and automatically remounted)
#define DISK_INSERT_CHECK 1
#else
#define DISK_INSERT_CHECK 0
#endif
@ -123,9 +125,6 @@ static DriveInfo *first_drive_info;
uint32 SonyDiskIconAddr;
uint32 SonyDriveIconAddr;
// Number of ticks between checks for disk insertion
const int driver_delay = 120;
// Flag: Control(accRun) has been called, interrupt routine is now active
static bool acc_run_called = false;
@ -520,18 +519,13 @@ int16 SonyStatus(uint32 pb, uint32 dce)
/*
* Driver interrupt routine - check for volumes to be mounted
* Driver interrupt routine (1Hz) - check for volumes to be mounted
*/
void SonyInterrupt(void)
{
static int tick_count = 0;
if (!acc_run_called)
return;
tick_count++;
if (tick_count > driver_delay) {
tick_count = 0;
mount_mountable_volumes();
}
mount_mountable_volumes();
}

View File

@ -19,6 +19,7 @@
*/
#include "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "emul_op.h"
@ -81,7 +82,9 @@ bool Init680x0(void)
#endif
init_m68k();
#ifdef USE_COMPILER
compiler_init();
#endif
return true;
}

View File

@ -43,7 +43,10 @@
* FDBcc:
* The loop termination condition was wrong.
* Possible leak from int16 to int32 fixed.
* Now fpcr high 16 bits are always read as zeores, no matter what was
* get_fp_value:
* Immediate addressing mode && Operation Length == Byte ->
* Use the low-order byte of the extension word.
* Now fpcr high 16 bits are always read as zeroes, no matter what was
* written to them.
*
* Other:
@ -377,7 +380,7 @@ static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
if( wrd2 | wrd3 ) {
// mantissa, not fraction.
uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
while( (man & UVAL64(0x8000000000000000)) == 0 ) {
while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) {
man <<= 1;
exp--;
}
@ -412,6 +415,53 @@ static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
return(result);
}
/*
Would be so much easier with full size floats :(
... this is so vague.
*/
static __inline__ void to_exten_no_normalize(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, uae_u32 *p
)
{
// double result;
// uae_u32 *p = (uae_u32 *)&result;
// Is it zero?
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
MAKE_ZERO_POSITIVE(p);
return;
}
// Is it NaN?
if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
MAKE_NAN( p );
return;
}
}
uae_u32 sign = wrd1 & 0x80000000;
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
if(exp < 16383 - 1023) {
// should set underflow.
exp = 0;
} else if(exp > 16383 + 1023) {
// should set overflow.
exp = 2047;
} else {
exp = exp + 1023 - 16383;
}
// drop the explicit integer bit.
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)(*(double *)p)));
// return(result);
}
static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
{
uae_u32 *p = (uae_u32 *)&src;
@ -459,10 +509,12 @@ static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2)
static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
{
/*
if (src == 0.0) {
*wrd1 = *wrd2 = 0;
return;
}
*/
uae_u32 *p = (uae_u32 *)&src;
*wrd2 = p[FLO];
*wrd1 = p[FHI];
@ -801,6 +853,9 @@ static __inline__ int get_fp_value (uae_u32 opcode, uae_u16 extra, double *src)
case 4:
ad = m68k_getpc ();
m68k_setpc (ad + sz2[size]);
// Immediate addressing mode && Operation Length == Byte ->
// Use the low-order byte of the extension word.
if(size == 6) ad++;
break;
default:
return 0;
@ -1053,14 +1108,14 @@ static __inline__ int get_fp_ad(uae_u32 opcode, uae_u32 * ad)
return 1;
}
static __inline__ int fpp_cond(uae_u32 opcode, int contition)
static __inline__ int fpp_cond(uae_u32 opcode, int condition)
{
int N = (regs.fpsr & 0x8000000) != 0;
int Z = (regs.fpsr & 0x4000000) != 0;
/* int I = (regs.fpsr & 0x2000000) != 0; */
int NotANumber = (regs.fpsr & 0x1000000) != 0;
#define N ((regs.fpsr & 0x8000000) != 0)
#define Z ((regs.fpsr & 0x4000000) != 0)
#define I ((regs.fpsr & 0x2000000) != 0)
#define NotANumber ((regs.fpsr & 0x1000000) != 0)
switch (contition) {
switch (condition) {
case 0x00:
CONDRET("False",0);
case 0x01:
@ -1126,11 +1181,16 @@ static __inline__ int fpp_cond(uae_u32 opcode, int contition)
CONDRET("Signaling Not Equal",!Z);
case 0x1f:
CONDRET("Signaling True",1);
default:
CONDRET("",-1);
}
CONDRET("",-1);
#undef N
#undef Z
#undef I
#undef NotANumber
}
void fdbcc_opp(uae_u32 opcode, uae_u16 extra)
void REGPARAM2 fdbcc_opp(uae_u32 opcode, uae_u16 extra)
{
uaecptr pc = (uae_u32) m68k_getpc ();
uae_s32 disp = (uae_s32) (uae_s16) next_iword();
@ -1161,7 +1221,7 @@ void fdbcc_opp(uae_u32 opcode, uae_u16 extra)
}
}
void fscc_opp(uae_u32 opcode, uae_u16 extra)
void REGPARAM2 fscc_opp(uae_u32 opcode, uae_u16 extra)
{
uae_u32 ad;
int cc;
@ -1184,7 +1244,7 @@ void fscc_opp(uae_u32 opcode, uae_u16 extra)
}
}
void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
void REGPARAM2 ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
{
int cc;
@ -1200,7 +1260,7 @@ void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
}
// NOTE that we get here also when there is a FNOP (nontrapping false, displ 0)
void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
void REGPARAM2 fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
{
int cc;
@ -1219,7 +1279,7 @@ void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
// FSAVE has no post-increment
// 0x1f180000 == IDLE state frame, coprocessor version number 1F
void fsave_opp(uae_u32 opcode)
void REGPARAM2 fsave_opp(uae_u32 opcode)
{
uae_u32 ad;
int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
@ -1278,7 +1338,7 @@ void fsave_opp(uae_u32 opcode)
}
// FRESTORE has no pre-decrement
void frestore_opp(uae_u32 opcode)
void REGPARAM2 frestore_opp(uae_u32 opcode)
{
uae_u32 ad;
uae_u32 d;
@ -1607,42 +1667,17 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
uae_u32 wrd1, wrd2, wrd3;
if( list & 0x80 ) {
from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3);
put_long (ad, wrd3);
put_long (ad, wrd1);
ad += 4;
put_long (ad, wrd2);
ad += 4;
put_long (ad, wrd1);
put_long (ad, wrd3);
ad += 4;
}
list <<= 1;
}
}
/*
while (list) {
uae_u32 wrd1, wrd2, wrd3;
if (incr < 0) {
from_exten(regs.fp[fpp_movem_index2[list]],
&wrd1, &wrd2, &wrd3);
ad -= 4;
put_long (ad, wrd3);
ad -= 4;
put_long (ad, wrd2);
ad -= 4;
put_long (ad, wrd1);
} else {
from_exten(regs.fp[fpp_movem_index1[list]],
&wrd1, &wrd2, &wrd3);
put_long (ad, wrd1);
ad += 4;
put_long (ad, wrd2);
ad += 4;
put_long (ad, wrd3);
ad += 4;
}
list = fpp_movem_next[list];
}
*/
if ((opcode & 0x38) == 0x18) // post-increment?
m68k_areg (regs, opcode & 7) = ad;
if ((opcode & 0x38) == 0x20) // pre-decrement?
@ -1685,13 +1720,14 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
for(reg=7; reg>=0; reg--) {
uae_u32 wrd1, wrd2, wrd3;
if( list & 0x80 ) {
wrd1 = get_long (ad);
ad -= 4;
wrd2 = get_long (ad);
ad -= 4;
wrd3 = get_long (ad);
ad -= 4;
regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
wrd2 = get_long (ad);
ad -= 4;
wrd1 = get_long (ad);
// regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
to_exten_no_normalize (wrd1, wrd2, wrd3, (uae_u32 *)&regs.fp[reg]);
}
list <<= 1;
}
@ -1705,36 +1741,12 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
ad += 4;
wrd3 = get_long (ad);
ad += 4;
regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
// regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
to_exten_no_normalize (wrd1, wrd2, wrd3, (uae_u32 *)&regs.fp[reg]);
}
list <<= 1;
}
}
/**/
/*
while (list) {
uae_u32 wrd1, wrd2, wrd3;
if (incr < 0) {
ad -= 4;
wrd3 = get_long (ad);
ad -= 4;
wrd2 = get_long (ad);
ad -= 4;
wrd1 = get_long (ad);
regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3);
} else {
wrd1 = get_long (ad);
ad += 4;
wrd2 = get_long (ad);
ad += 4;
wrd3 = get_long (ad);
ad += 4;
regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3);
}
list = fpp_movem_next[list];
}
*/
if ((opcode & 0x38) == 0x18) // post-increment?
m68k_areg (regs, opcode & 7) = ad;
if ((opcode & 0x38) == 0x20) // pre-decrement?
@ -1865,6 +1877,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
dump_fp_regs( "END ");
return;
}
D(bug("returned from get_fp_value m68k_getpc()=%X\r\n",m68k_getpc()));
switch (extra & 0x7f) {
case 0x00: /* FMOVE */
@ -1983,6 +1996,8 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
MAKE_FPSR(regs.fpsr,regs.fp[reg]);
break;
case 0x18: /* FABS */
case 0x58: /* single precision rounding */
case 0x5C: /* double precision rounding */
D(bug("FABS %.04f\r\n",(float)src));
regs.fp[reg] = src < 0 ? -src : src;
MAKE_FPSR(regs.fpsr,regs.fp[reg]);
@ -2065,6 +2080,8 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
}
break;
case 0x22: /* FADD */
case 0x62: /* single */
case 0x66: /* double */
D(bug("FADD %.04f\r\n",(float)src));
regs.fp[reg] += src;
MAKE_FPSR(regs.fpsr,regs.fp[reg]);
@ -2206,7 +2223,8 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
}
} else {
double tmp = regs.fp[reg] - src;
regs.fpsr = (regs.fpsr & 0x00FFFFFF) | (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0);
// regs.fpsr = (regs.fpsr & 0x00FFFFFF) | (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0);
regs.fpsr = (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0);
}
#else
{
@ -2226,6 +2244,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 extra)
op_illg (opcode);
break;
}
D(bug("END m68k_getpc()=%X\r\n",m68k_getpc()));
dump_fp_regs( "END ");
return;
}