From 46612d3008e49a15b132a6e71b190352cf26acf6 Mon Sep 17 00:00:00 2001 From: jlachmann <> Date: Sun, 20 Aug 2000 14:08:44 +0000 Subject: [PATCH] added MacsBug Support -jl- --- BasiliskII/ChangeLog | 4 + BasiliskII/src/AmigaOS/asm_support.asm | 319 ++++++++++++++++-- BasiliskII/src/AmigaOS/ether_amiga.cpp | 43 ++- BasiliskII/src/AmigaOS/main_amiga.cpp | 38 ++- BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp | 77 ++++- BasiliskII/src/AmigaOS/user_strings_amiga.cpp | 2 + BasiliskII/src/AmigaOS/user_strings_amiga.h | 5 +- BasiliskII/src/AmigaOS/video_amiga.cpp | 13 +- BasiliskII/src/emul_op.cpp | 30 +- BasiliskII/src/include/emul_op.h | 1 + BasiliskII/src/include/macos_util.h | 14 + BasiliskII/src/include/main.h | 4 +- BasiliskII/src/include/video_defs.h | 8 + BasiliskII/src/macos_util.cpp | 21 ++ BasiliskII/src/rom_patches.cpp | 33 +- BasiliskII/src/video.cpp | 12 +- 16 files changed, 553 insertions(+), 71 deletions(-) diff --git a/BasiliskII/ChangeLog b/BasiliskII/ChangeLog index 91c05403..0d78327f 100644 --- a/BasiliskII/ChangeLog +++ b/BasiliskII/ChangeLog @@ -1,3 +1,7 @@ +V0.8 (snapshot) - + - AmigaOS: added MacsBug support (tested with MacsBug6.6.1), + fixed bug [Jürgen Lachmann] + V0.8 (snapshot) - - AmigaOS: enabled floppy support, fixed floppy bugs [Jürgen Lachmann] - AmigaOS: Amiga mouse pointer is hidden inside windowed Mac displays diff --git a/BasiliskII/src/AmigaOS/asm_support.asm b/BasiliskII/src/AmigaOS/asm_support.asm index 76518c9a..f472929a 100644 --- a/BasiliskII/src/AmigaOS/asm_support.asm +++ b/BasiliskII/src/AmigaOS/asm_support.asm @@ -35,6 +35,7 @@ XDEF _Scod060Patch1 XDEF _Scod060Patch2 XDEF _ThInitFPUPatch + XDEF _AsmTriggerNMI XREF _OldTrapHandler XREF _OldExceptionHandler @@ -46,6 +47,7 @@ XREF _MainTask XREF _SysBase XREF _quit_emulator + XREF _kprintf SECTION text,CODE @@ -183,10 +185,10 @@ _ExceptionHandlerAsm pea 1$ move.w _EmulatedSR,d0 move.w d0,-(sp) - or.w #$2100,d0 ;Set interrupt level in SR + or.w #$0100,d0 ;Set interrupt level in SR move.w d0,_EmulatedSR - move.l $64.w,a0 ;Jump to MacOS interrupt handler - jmp (a0) + move.l $64.w,-(sp) ;Jump to MacOS interrupt handler + rts 1$ move.l (sp)+,d0 ;Restore d0 rts @@ -277,16 +279,64 @@ _ThInitFPUPatch tst.b $40(a4) * Trap handler of main task * -_TrapHandlerAsm cmp.l #4,(sp) ;Illegal instruction? +_TrapHandlerAsm: + cmp.l #4,(sp) ;Illegal instruction? beq.s doillinstr cmp.l #10,(sp) ;A-Line exception? beq.s doaline cmp.l #8,(sp) ;Privilege violation? beq.s doprivviol + cmp.l #9,(sp) ;Trace? + beq dotrace + cmp.l #3,(sp) ;Illegal Address? + beq.s doilladdr - move.l _OldTrapHandler,-(sp) ;No, jump to old trap handler + cmp.l #32,(sp) + blt 1$ + cmp.l #47,(sp) + ble doTrapXX ; Vector 32-47 : TRAP #0 - 15 Instruction Vectors + +1$: move.l _OldTrapHandler,-(sp) ;No, jump to old trap handler rts +* +* TRAP #0 - 15 Instruction Vectors +* + +doTrapXX: move.l a0,(sp) ;Save a0 + move.l usp,a0 ;Get user stack pointer + move.l 2*4(sp),-(a0) ;Copy 4-word stack frame to user stack + move.l 1*4(sp),-(a0) + move.l a0,usp ;Update USP + move.l (sp)+,a0 ;Restore a0 + + addq.l #4*2,sp ;Remove exception frame from supervisor stack + andi #$d8ff,sr ;Switch to user mode, enable interrupts + + move.l $2d*4.w,-(sp) ;Jump to MacOS exception handler + rts + + +* +* trace Vector +* + +dotrace: move.l a0,(sp) ;Save a0 + + move.l usp,a0 ;Get user stack pointer + move.l 3*4(sp),-(a0) ;Copy 6-word stack frame to user stack + move.l 2*4(sp),-(a0) + move.l 1*4(sp),-(a0) + move.l a0,usp ;Update USP + move.l (sp)+,a0 ;Restore a0 + + lea 6*2(sp),sp ;Remove exception frame from supervisor stack + andi #$18ff,sr ;Switch to user mode, enable interrupts, disable trace + + move.l $24.w,-(sp) ;Jump to MacOS exception handler + rts + + * * A-Line handler: call MacOS A-Line handler * @@ -301,15 +351,75 @@ doaline move.l a0,(sp) ;Save a0 addq.l #8,sp ;Remove exception frame from supervisor stack andi #$d8ff,sr ;Switch to user mode, enable interrupts + IFNE 0 + +; move.w ([2,sp]),($3800) + + cmp.w #$a9c3,([2,sp]) + bne 1$ + + move.l d0,-(sp) + move.l a0,-(sp) + pea afmt(pc) + jsr _kprintf + lea 3*4(sp),sp +1$: + ENDC + move.l $28.w,-(sp) ;Jump to MacOS exception handler rts +afmt: dc.b 'a0=%08lx d0=%08lx\n',0 + cnop 0,4 + +* +* Illegal address handler +* + +doilladdr: move.l a0,(sp) ;Save a0 + + move.l usp,a0 ;Get user stack pointer + move.l 3*4(sp),-(a0) ;Copy 6-word stack frame to user stack + move.l 2*4(sp),-(a0) + move.l 1*4(sp),-(a0) + move.l a0,usp ;Update USP + move.l (sp)+,a0 ;Restore a0 + + lea 6*2(sp),sp ;Remove exception frame from supervisor stack + andi #$d8ff,sr ;Switch to user mode, enable interrupts + + move.l $0c.w,-(sp) ;Jump to MacOS exception handler + rts + + * * Illegal instruction handler: call IllInstrHandler() (which calls EmulOp()) * to execute extended opcodes (see emul_op.h) * -doillinstr move.l a6,(sp) ;Save a6 +doillinstr + movem.l a0/d0,-(sp) + move.w ([6+2*4,sp]),d0 + and.w #$ff00,d0 + cmp.w #$7100,d0 + movem.l (sp)+,a0/d0 + beq 1$ + + move.l a0,(sp) ;Save a0 + move.l usp,a0 ;Get user stack pointer + move.l 8(sp),-(a0) ;Copy stack frame to user stack + move.l 4(sp),-(a0) + move.l a0,usp ;Update USP + move.l (sp)+,a0 ;Restore a0 + + add.w #3*4,sp ;Remove exception frame from supervisor stack + andi #$d8ff,sr ;Switch to user mode, enable interrupts + + move.l $10.w,-(sp) ;Jump to MacOS exception handler + rts + +1$: + move.l a6,(sp) ;Save a6 move.l usp,a6 ;Get user stack pointer move.l a6,-10(a6) ;Push USP (a7) @@ -364,12 +474,16 @@ doprivviol move.l d0,(sp) ;Save d0 cmp.w #$40d0,d0 ;move sr,(a0)? beq movefromsra0 cmp.w #$40d7,d0 ;move sr,(sp)? - beq movefromsra0 + beq movefromsrsp ;+++jl+++ cmp.w #$f327,d0 ;fsave -(sp)? beq fsavepush cmp.w #$f35f,d0 ;frestore (sp)+? beq frestorepop + cmp.w #$f32d,d0 ;fsave xxx(a5) ? + beq fsavea5 + cmp.w #$f36d,d0 ;frestore xxx(a5) ? + beq frestorea5 cmp.w #$4e73,d0 ;rte? beq pvrte @@ -418,6 +532,14 @@ doprivviol move.l d0,(sp) ;Save d0 cmp.w #$f4f8,d0 ;cpusha dc/ic? beq cpushadcic + cmp.w #$4e69,d0 ;move usp,a1 + beq moveuspa1 + cmp.w #$4e68,d0 ;move usp,a0 + beq moveuspa0 + + cmp.w #$4e61,d0 ;move a1,usp + beq moved1usp + pv_unhandled move.l (sp),d0 ;Unhandled instruction, jump to handler in main.cpp move.l a6,(sp) ;Save a6 move.l usp,a6 ;Get user stack pointer @@ -459,7 +581,7 @@ popsr move.l a0,-(sp) ;Save a0 move.w (a0)+,d0 ;Get SR from user stack move.w d0,8(sp) ;Store into CCR on exception stack frame and.w #$00ff,8(sp) - and.w #$2700,d0 ;Extract supervisor bits + and.w #$e700,d0 ;Extract supervisor bits move.w d0,_EmulatedSR ;And save them and.w #$0700,d0 ;Rethrow exception if interrupts are pending and reenabled @@ -485,7 +607,7 @@ orisr move.w 4(sp),d0 ;Get CCR from stack or.w ([6,sp],2),d0 ;Or with immediate value move.w d0,4(sp) ;Store into CCR on stack and.w #$00ff,4(sp) - and.w #$2700,d0 ;Extract supervisor bits + and.w #$e700,d0 ;Extract supervisor bits move.w d0,_EmulatedSR ;And save them move.l (sp)+,d0 ;Restore d0 addq.l #4,2(sp) ;Skip instruction @@ -497,7 +619,7 @@ andisr move.w 4(sp),d0 ;Get CCR from stack and.w ([6,sp],2),d0 ;And with immediate value storesr4 move.w d0,4(sp) ;Store into CCR on stack and.w #$00ff,4(sp) - and.w #$2700,d0 ;Extract supervisor bits + and.w #$e700,d0 ;Extract supervisor bits move.w d0,_EmulatedSR ;And save them and.w #$0700,d0 ;Rethrow exception if interrupts are pending and reenabled @@ -584,21 +706,73 @@ frestorepop move.l (sp),d0 ;Restore d0 addq.l #2,2(sp) ;Skip instruction rte -; rte (only handles format 0) -pvrte move.l a0,-(sp) ;Save a0 - move.l usp,a0 ;Get user stack pointer - move.w (a0)+,d0 ;Get SR from user stack - move.w d0,8(sp) ;Store into CCR on exception stack frame - and.w #$00ff,8(sp) - and.w #$2700,d0 ;Extract supervisor bits - move.w d0,_EmulatedSR ;And save them - move.l (a0)+,10(sp) ;Store return address in exception stack frame - addq.l #2,a0 ;Skip format word - move.l a0,usp ;Update USP +; frestore xxx(a5) +jl+ +frestorea5 move.l (sp),d0 ;Restore d0 + move.l a0,(sp) ;Save a0 + move.l a5,a0 ;Get base register + add.w ([6,sp],2),a0 ;Add offset to base register + frestore (a0) ;Restore FP state from (a0) move.l (sp)+,a0 ;Restore a0 + addq.l #4,2(sp) ;Skip instruction + rte + +; fsave xxx(a5) +jl+ +fsavea5: move.l (sp),d0 ;Restore d0 + move.l a0,(sp) ;Save a0 + move.l a5,a0 ;Get base register + add.w ([6,sp],2),a0 ;Add offset to base register + fsave (a0) ;Push FP state to (a0) + move.l (sp)+,a0 ;Restore a0 + addq.l #4,2(sp) ;Skip instruction + rte + +; rte +pvrte movem.l a0/a1,-(sp) ;Save a0 and a1 + move.l usp,a0 ;Get user stack pointer + + move.w (a0)+,d0 ;Get SR from user stack + move.w d0,8+4(sp) ;Store into CCR on exception stack frame + and.w #$c0ff,8+4(sp) + and.w #$e700,d0 ;Extract supervisor bits + move.w d0,_EmulatedSR ;And save them + move.l (a0)+,10+4(sp) ;Store return address in exception stack frame + + move.w (a0)+,d0 ;get format word + lsr.w #7,d0 ;get stack frame Id + lsr.w #4,d0 + and.w #$001e,d0 + move.w (StackFormatTable,pc,d0.w),d0 ; get total stack frame length + subq.w #4,d0 ; count only extra words + lea 16+4(sp),a1 ; destination address (in supervisor stack) + bra 1$ + +2$: move.w (a0)+,(a1)+ ; copy additional stack words back to supervisor stack +1$: dbf d0,2$ + + move.l a0,usp ;Update USP + movem.l (sp)+,a0/a1 ;Restore a0 and a1 move.l (sp)+,d0 ;Restore d0 rte +; sizes of exceptions stack frames +StackFormatTable: + dc.w 4 ; Four-word stack frame, format $0 + dc.w 4 ; Throwaway four-word stack frame, format $1 + dc.w 6 ; Six-word stack frame, format $2 + dc.w 6 ; MC68040 floating-point post-instruction stack frame, format $3 + dc.w 8 ; MC68EC040 and MC68LC040 floating-point unimplemented stack frame, format $4 + dc.w 4 ; Format $5 + dc.w 4 ; Format $6 + dc.w 30 ; MC68040 access error stack frame, Format $7 + dc.w 29 ; MC68010 bus and address error stack frame, format $8 + dc.w 10 ; MC68020 and MC68030 coprocessor mid-instruction stack frame, format $9 + dc.w 16 ; MC68020 and MC68030 short bus cycle stack frame, format $a + dc.w 46 ; MC68020 and MC68030 long bus cycle stack frame, format $b + dc.w 12 ; CPU32 bus error for prefetches and operands stack frame, format $c + dc.w 4 ; Format $d + dc.w 4 ; Format $e + dc.w 4 ; Format $f + ; move sr,dx movefromsrd0 addq.l #4,sp ;Skip saved d0 moveq #0,d0 @@ -660,7 +834,7 @@ movefromsrd7 move.l (sp)+,d0 movetosrd0 move.l (sp),d0 storesr2 move.w d0,4(sp) and.w #$00ff,4(sp) - and.w #$2700,d0 + and.w #$e700,d0 move.w d0,_EmulatedSR and.w #$0700,d0 ;Rethrow exception if interrupts are pending and reenabled @@ -705,6 +879,8 @@ movecfromcr move.w ([6,sp],2),d0 ;Get next instruction word beq.s movecvbra0 cmp.w #$9801,d0 ;movec vbr,a1? beq.s movecvbra1 + cmp.w #$1801,d0 ;movec vbr,d1? + beq movecvbrd1 cmp.w #$0002,d0 ;movec cacr,d0? beq.s moveccacrd0 cmp.w #$1002,d0 ;movec cacr,d1? @@ -713,6 +889,22 @@ movecfromcr move.w ([6,sp],2),d0 ;Get next instruction word beq.s movectcd0 cmp.w #$1003,d0 ;movec tc,d1? beq.s movectcd1 + cmp.w #$1000,d0 ;movec SFC,d1? + beq movecsfcd1 + cmp.w #$1001,d0 ;movec DFC,d1? + beq movecdfcd1 + cmp.w #$0806,d0 ;movec URP,d0? + beq movecurpd0 + cmp.w #$0807,d0 ;movec SRP,d0? + beq.s movecsrpd0 + cmp.w #$0004,d0 ;movec ITT0,d0 + beq.s movecitt0d0 + cmp.w #$0005,d0 ;movec ITT1,d0 + beq.s movecitt1d0 + cmp.w #$0006,d0 ;movec DTT0,d0 + beq.s movecdtt0d0 + cmp.w #$0007,d0 ;movec DTT1,d0 + beq.s movecdtt1d0 bra pv_unhandled @@ -740,27 +932,62 @@ movecvbra1 move.l (sp)+,d0 addq.l #4,2(sp) rte +; movec vbr,d1 +movecvbrd1 move.l (sp)+,d0 + moveq.l #0,d1 ;VBR always appears to be at 0 + addq.l #4,2(sp) + rte + ; movec tc,d0 movectcd0 addq.l #4,sp moveq #0,d0 ;MMU is always off addq.l #4,2(sp) rte -; movec tc,d1 -movectcd1 addq.l #4,sp +; movec tc,d1 +jl+ +movectcd1 move.l (sp)+,d0 ;Restore d0 moveq #0,d1 ;MMU is always off addq.l #4,2(sp) rte +; movec SFC,d1 +jl+ +movecsfcd1: move.l (sp)+,d0 ;Restore d0 + moveq #0,d1 ;MMU is always off + addq.l #4,2(sp) + rte + +; movec DFC,d1 +jl+ +movecdfcd1: move.l (sp)+,d0 ;Restore d0 + moveq #0,d1 ;MMU is always off + addq.l #4,2(sp) + rte + +movecurpd0: ; movec URP,d0 +jl+ +movecsrpd0: ; movec SRP,d0 +movecitt0d0: ; movec ITT0,d0 +movecitt1d0: ; movec ITT1,d0 +movecdtt0d0: ; movec DTT0,d0 +movecdtt1d0: ; movec DTT1,d0 + addq.l #4,sp + moveq.l #0,d0 ;MMU is always off + addq.l #4,2(sp) ;skip instruction + rte + ; movec x,cr movectocr move.w ([6,sp],2),d0 ;Get next instruction word cmp.w #$0801,d0 ;movec d0,vbr? beq.s movectovbr + cmp.w #$1801,d0 ;movec d1,vbr? + beq.s movectovbr cmp.w #$0002,d0 ;movec d0,cacr? beq.s movectocacr cmp.w #$1002,d0 ;movec d1,cacr? beq.s movectocacr + cmp.w #$1000,d0 ;movec d1,SFC? + beq.s movectoxfc + cmp.w #$1001,d0 ;movec d1,DFC? + beq.s movectoxfc bra pv_unhandled @@ -778,6 +1005,12 @@ movectocacr movem.l d1/a0-a1/a6,-(sp) ;Move to CACR, clear caches addq.l #4,2(sp) rte +; movec x,SFC +; movec x,DFC +movectoxfc move.l (sp)+,d0 ;Ignore moves to SFC, DFC + addq.l #4,2(sp) + rte + ; cpusha cpushadc cpushadcic movem.l d1/a0-a1/a6,-(sp) ;Clear caches @@ -788,4 +1021,42 @@ cpushadcic movem.l d1/a0-a1/a6,-(sp) ;Clear caches addq.l #2,2(sp) rte +; move usp,a1 +jl+ +moveuspa1: move.l (sp)+,d0 + move usp,a1 + addq.l #2,2(sp) + rte + +; move usp,a0 +jl+ +moveuspa0: move.l (sp)+,d0 + move usp,a0 + addq.l #2,2(sp) + rte + +; move a1,usp +jl+ +moved1usp: move.l (sp)+,d0 + move a1,usp + addq.l #2,2(sp) + rte + +; +; Trigger NMI (Pop up debugger) +; + +_AsmTriggerNMI: + move.l d0,-(sp) ;Save d0 + move.w #$007c,-(sp) ;Yes, fake NMI stack frame + pea 1$ + move.w _EmulatedSR,d0 + and.w #$f8ff,d0 ;Set interrupt level in SR + move.w d0,-(sp) + move.w d0,_EmulatedSR + + move.l $7c.w,-(sp) ;Jump to MacOS NMI handler + rts + +1$ move.l (sp)+,d0 ;Restore d0 + rts + + END diff --git a/BasiliskII/src/AmigaOS/ether_amiga.cpp b/BasiliskII/src/AmigaOS/ether_amiga.cpp index 7c3fce44..53c152a5 100644 --- a/BasiliskII/src/AmigaOS/ether_amiga.cpp +++ b/BasiliskII/src/AmigaOS/ether_amiga.cpp @@ -1,7 +1,7 @@ /* * ether_amiga.cpp - Ethernet device driver, AmigaOS specific stuff * - * Basilisk II (C) 1997-2000 Christian Bauer + * Basilisk II (C) 1997-1999 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 @@ -346,6 +346,8 @@ static __saveds __regargs LONG copy_from_buff(uint8 *to /*a0*/, char *wds /*a1*/ 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; @@ -388,13 +390,48 @@ static __saveds void net_func(void) // Parse device name char dev_name[256]; ULONG dev_unit; - if (sscanf(PrefsFindString("ether"), "%[^/]/%ld", dev_name, &dev_unit) < 2) + + 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 (1 != sscanf(LastSlash, "/%ld", &dev_unit)) + goto quit; + +// printf("dev=<%s> unit=%d\n", dev_name, dev_unit); + } + else + { + if (2 != sscanf(str, "%[^/]/%ld", dev_name, &dev_unit)) + goto quit; + } + } + else goto quit; // Open device control_io->ios2_BufferManagement = buffer_tags; - if (OpenDevice((UBYTE *)dev_name, dev_unit, (struct IORequest *)control_io, 0) || control_io->ios2_Req.io_Device == 0) + od_error = OpenDevice((UBYTE *)dev_name, dev_unit, (struct IORequest *)control_io, 0); + if (0 != od_error || 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? diff --git a/BasiliskII/src/AmigaOS/main_amiga.cpp b/BasiliskII/src/AmigaOS/main_amiga.cpp index 87241f67..44159547 100644 --- a/BasiliskII/src/AmigaOS/main_amiga.cpp +++ b/BasiliskII/src/AmigaOS/main_amiga.cpp @@ -75,6 +75,8 @@ uint32 ROMBaseMac; // ROM base (Mac address space) uint8 *ROMBaseHost; // ROM base (host address space) uint32 ROMSize; // Size of ROM +uint32 MacsBugFlags = 0xbff; + // CPU and FPU type, addressing mode int CPUType; @@ -242,11 +244,28 @@ int main(void) WarningAlert(GetString(STR_SMALL_RAM_WARN)); RAMSize = 1024*1024; } - RAMBaseHost = (uint8 *)AllocMem(RAMSize + 0x100000, MEMF_PUBLIC); - if (RAMBaseHost == NULL) { - ErrorAlert(GetString(STR_NO_MEM_ERR)); - QuitEmulator(); - } + RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC); +// if (RAMBaseHost == NULL) { +// ErrorAlert(GetString(STR_NO_MEM_ERR)); +// QuitEmulator(); +// } + if (RAMBaseHost == NULL) + { + uint32 newRAMSize = AvailMem(MEMF_LARGEST) - 0x100000; + char xText[120]; + + sprintf(xText, GetString(STR_NOT_ENOUGH_MEM_WARN), RAMSize, newRAMSize); + + if (1 != ChoiceAlert(xText, "Use", "Quit")) + QuitEmulator(); + + RAMSize = newRAMSize; + RAMBaseHost = (uint8 *)AllocVec(RAMSize + 0x100000, MEMF_PUBLIC); + if (RAMBaseHost == NULL) { + ErrorAlert(GetString(STR_NO_MEM_ERR)); + QuitEmulator(); + } + } RAMBaseMac = (uint32)RAMBaseHost; D(bug("Mac RAM starts at %08lx\n", RAMBaseHost)); ROMBaseHost = RAMBaseHost + RAMSize; @@ -313,6 +332,8 @@ int main(void) // Set task priority to -1 so we don't use all processing time SetTaskPri(MainTask, -1); + WriteMacInt32(MacsBugFlags, 0); + // Swap stack to Mac RAM area stack_swap.stk_Lower = RAMBaseHost; stack_swap.stk_Upper = (ULONG)RAMBaseHost + RAMSize; @@ -375,7 +396,7 @@ void QuitEmulator(void) // Delete RAM/ROM area if (RAMBaseHost) - FreeMem(RAMBaseHost, RAMSize + 0x100000); + FreeVec(RAMBaseHost); // Delete scratch memory area if (ScratchMem) @@ -453,6 +474,11 @@ void TriggerInterrupt(void) Signal(MainTask, IRQSigMask); } +void TriggerNMI(void) +{ + AsmTriggerNMI(); +} + /* * 60Hz thread diff --git a/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp b/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp index cb96caaa..f25fa074 100644 --- a/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp +++ b/BasiliskII/src/AmigaOS/prefs_editor_amiga.cpp @@ -1,7 +1,7 @@ /* * prefs_editor_amiga.cpp - Preferences editor, AmigaOS implementation (using gtlayout.library) * - * Basilisk II (C) 1997-2000 Christian Bauer + * Basilisk II (C) 1997-1999 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 @@ -27,7 +27,7 @@ #include #include #include -#include +#include // jl #include #include #include @@ -38,7 +38,7 @@ #include #include #include -#include +#include // jl #include #include "sysdeps.h" @@ -428,10 +428,30 @@ bool PrefsEditor(void) case GAD_SCSI6_DEVICE: case GAD_SERIALA_DEVICE: case GAD_SERIALB_DEVICE: + if (dev_request) { + LT_LockWindow(win); + BOOL result = AslRequestTags(dev_request, + ASLFR_Window, (ULONG)win, + ASLFR_InitialDrawer, (ULONG) "Devs:", + TAG_END); + LT_UnlockWindow(win); + if (result) { + char *str; + GT_GetGadgetAttrs(gad, win, NULL, GTST_String, (ULONG)&str, TAG_END); + strncpy(str, dev_request->rf_File, 255); // Don't copy the directory part. This is usually "DEVS:" and we don't need that. + str[255] = 0; + LT_SetAttributes(h, gad->GadgetID, GTST_String, (ULONG)str, TAG_END); + } + } + break; + case GAD_ETHER_DEVICE: if (dev_request) { LT_LockWindow(win); - BOOL result = AslRequestTags(dev_request, ASLFR_Window, (ULONG)win, TAG_END); + BOOL result = AslRequestTags(dev_request, + ASLFR_Window, (ULONG)win, + ASLFR_InitialDrawer, (ULONG) "Devs:Networks", + TAG_END); LT_UnlockWindow(win); if (result) { char *str; @@ -513,7 +533,7 @@ quit: FreeAslRequest(dev_request); FreeAslRequest(file_request); - // Delete menus + // Delete Menus jl LT_DisposeMenu(menu); // Delete handle @@ -1251,20 +1271,24 @@ static void screen_mode_req(struct Window *win, struct LayoutHandle *h) ULONG id; - if (P96Base) { + if (CyberGfxBase) + { + UWORD ModelArray[] = { PIXFMT_LUT8, PIXFMT_RGB15, PIXFMT_ARGB32, 0, ~0 }; + + id = (ULONG) CModeRequestTags(NULL, + CYBRMREQ_MinDepth, 8, + CYBRMREQ_CModelArray, (ULONG) ModelArray, + TAG_END + ); + } + else + { id = p96RequestModeIDTags( P96MA_MinDepth, 8, P96MA_FormatsAllowed, RGBFF_CLUT | RGBFF_R5G5B5 | RGBFF_A8R8G8B8, TAG_END ); - } else { - UWORD model_array[] = {PIXFMT_LUT8, PIXFMT_RGB16, PIXFMT_ARGB32, 0, ~0}; - id = (ULONG) CModeRequestTags(NULL, - CYBRMREQ_MinDepth, 8, - CYBRMREQ_CModelArray, (ULONG)model_array, - TAG_END - ); - } + } LT_UnlockWindow(win); if (id != INVALID_ID) { @@ -1446,7 +1470,29 @@ static void parse_serial_prefs(void) const char *str = PrefsFindString("ether"); if (str) - sscanf(str, "%[^/]/%ld", ether_dev, ðer_unit); + { + 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 = ether_dev; + + while (lp != LastSlash) + *dp++ = *lp++; + *dp = '\0'; + + sscanf(LastSlash, "/%ld", ðer_unit); + +// printf("dev=<%s> unit=%d\n", ether_dev, ether_unit); + } + else + { + sscanf(str, "%[^/]/%ld", ether_dev, ðer_unit); + } + } } // Set serial preference item @@ -1468,6 +1514,7 @@ static void read_serial_settings(void) if (strlen(ether_dev)) { char str[256]; + sprintf(str, "%s/%ld", ether_dev, ether_unit); PrefsReplaceString("ether", str); } else diff --git a/BasiliskII/src/AmigaOS/user_strings_amiga.cpp b/BasiliskII/src/AmigaOS/user_strings_amiga.cpp index 3a7d95c4..afc1bc7b 100644 --- a/BasiliskII/src/AmigaOS/user_strings_amiga.cpp +++ b/BasiliskII/src/AmigaOS/user_strings_amiga.cpp @@ -46,6 +46,8 @@ user_string_def platform_strings[] = { {STR_NO_AHI_CTRL_WARN, "Cannot open AHI control structure. Audio output will be disabled."}, {STR_AHI_MODE_CTRL, "AHI Mode"}, + {STR_NOT_ENOUGH_MEM_WARN, "Could not get %lu MBytes of memory.\nShould I use the largest Block (%lu MBytes) instead ?"}, + {-1, NULL} // End marker }; diff --git a/BasiliskII/src/AmigaOS/user_strings_amiga.h b/BasiliskII/src/AmigaOS/user_strings_amiga.h index 16094224..750ee1b5 100644 --- a/BasiliskII/src/AmigaOS/user_strings_amiga.h +++ b/BasiliskII/src/AmigaOS/user_strings_amiga.h @@ -1,7 +1,7 @@ /* * user_strings_amiga.h - AmigaOS-specific localizable strings * - * Basilisk II (C) 1997-2000 Christian Bauer + * Basilisk II (C) 1997-1999 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 @@ -37,7 +37,8 @@ enum { STR_NO_AHI_WARN, STR_NO_AHI_CTRL_WARN, - STR_AHI_MODE_CTRL + STR_AHI_MODE_CTRL, + STR_NOT_ENOUGH_MEM_WARN, }; #endif diff --git a/BasiliskII/src/AmigaOS/video_amiga.cpp b/BasiliskII/src/AmigaOS/video_amiga.cpp index bd98c02f..6e896180 100644 --- a/BasiliskII/src/AmigaOS/video_amiga.cpp +++ b/BasiliskII/src/AmigaOS/video_amiga.cpp @@ -33,6 +33,7 @@ #include #include "sysdeps.h" +#include "cpu_emulation.h" #include "main.h" #include "adb.h" #include "prefs.h" @@ -284,7 +285,8 @@ static bool init_screen_cgfx(ULONG mode_id) break; case 15: case 16: - if (format != PIXFMT_RGB16) { + // !!! PIXFMT_RGB15 is correct !!! + if (format != PIXFMT_RGB15) { ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR)); return false; } @@ -653,6 +655,15 @@ static __saveds void periodic_func(void) case IDCMP_RAWKEY: if (qualifier & IEQUALIFIER_REPEAT) // Keyboard repeat is done by MacOS break; + if ((IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL) == + (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL)) + && 0x5f == code) + { + SetInterruptFlag(INTFLAG_NMI); + TriggerInterrupt(); + break; + } + if (code & IECODE_UP_PREFIX) ADBKeyUp(keycode2mac[code & 0x7f]); else diff --git a/BasiliskII/src/emul_op.cpp b/BasiliskII/src/emul_op.cpp index f366d892..d6ae8486 100644 --- a/BasiliskII/src/emul_op.cpp +++ b/BasiliskII/src/emul_op.cpp @@ -60,10 +60,10 @@ void EmulOp(uint16 opcode, M68kRegisters *r) switch (opcode) { case M68K_EMUL_BREAK: { // Breakpoint printf("*** Breakpoint\n"); - printf("d0 %08x d1 %08x d2 %08x d3 %08x\n" - "d4 %08x d5 %08x d6 %08x d7 %08x\n" - "a0 %08x a1 %08x a2 %08x a3 %08x\n" - "a4 %08x a5 %08x a6 %08x a7 %08x\n" + 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], @@ -478,6 +478,13 @@ void EmulOp(uint16 opcode, M68kRegisters *r) ClearInterruptFlag(INTFLAG_AUDIO); AudioInterrupt(); } + + if (InterruptFlags & INTFLAG_NMI) { + ClearInterruptFlag(INTFLAG_NMI); + if (HasMacStarted()) { + TriggerNMI(); + } + } break; case M68K_EMUL_OP_PUT_SCRAP: { // PutScrap() patch @@ -520,12 +527,17 @@ void EmulOp(uint16 opcode, M68kRegisters *r) memmove(Mac2HostAddr(r->a[1]), Mac2HostAddr(r->a[0]), r->d[0]); break; + case M68K_EMUL_OP_DEBUGUTIL: + // printf("DebugUtil d0=%08lx a5=%08lx\n", r->d[0], r->a[5]); + r->d[0] = DebugUtil(r->d[0]); + break; + default: - printf("FATAL: EMUL_OP called with bogus opcode %04x\n", opcode); - printf("d0 %08x d1 %08x d2 %08x d3 %08x\n" - "d4 %08x d5 %08x d6 %08x d7 %08x\n" - "a0 %08x a1 %08x a2 %08x a3 %08x\n" - "a4 %08x a5 %08x a6 %08x a7 %08x\n" + printf("FATAL: EMUL_OP called with bogus opcode %08x\n", opcode); + 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], diff --git a/BasiliskII/src/include/emul_op.h b/BasiliskII/src/include/emul_op.h index 66d7cd6e..8e9846ad 100644 --- a/BasiliskII/src/include/emul_op.h +++ b/BasiliskII/src/include/emul_op.h @@ -87,6 +87,7 @@ enum { M68K_EMUL_OP_SOUNDIN_CONTROL, M68K_EMUL_OP_SOUNDIN_STATUS, M68K_EMUL_OP_SOUNDIN_CLOSE, + M68K_EMUL_OP_DEBUGUTIL, M68K_EMUL_OP_MAX // highest number }; diff --git a/BasiliskII/src/include/macos_util.h b/BasiliskII/src/include/macos_util.h index 25619c0b..8db49ce9 100644 --- a/BasiliskII/src/include/macos_util.h +++ b/BasiliskII/src/include/macos_util.h @@ -245,11 +245,25 @@ enum { // DeferredTask struct }; +// Definitions for DebugUtil() Selector +enum { + duDebuggerGetMax = 0, + duDebuggerEnter = 1, + duDebuggerExit = 2, + duDebuggerPoll = 3, + duGetPageState = 4, + duPageFaultFatal = 5, + duDebuggerLockMemory = 6, + duDebuggerUnlockMemory = 7, + duEnterSupervisorMode = 8 +}; + // Functions 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 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 +extern uint32 DebugUtil(uint32 Selector); // DebugUtil() Replacement // Construct four-character-code from string #define FOURCC(a,b,c,d) (((uint32)(a) << 24) | ((uint32)(b) << 16) | ((uint32)(c) << 8) | (uint32)(d)) diff --git a/BasiliskII/src/include/main.h b/BasiliskII/src/include/main.h index 6d0a78c5..d4cdf8ac 100644 --- a/BasiliskII/src/include/main.h +++ b/BasiliskII/src/include/main.h @@ -56,11 +56,13 @@ enum { INTFLAG_SERIAL = 4, // Serial driver INTFLAG_ETHER = 8, // Ethernet driver INTFLAG_AUDIO = 16, // Audio block read - INTFLAG_TIMER = 32 // Time Manager + INTFLAG_TIMER = 32, // Time Manager + INTFLAG_NMI = 64 // NMI }; extern uint32 InterruptFlags; // Currently pending interrupts extern void SetInterruptFlag(uint32 flag); // Set/clear interrupt flags extern void ClearInterruptFlag(uint32 flag); +extern void TriggerNMI(void); #endif diff --git a/BasiliskII/src/include/video_defs.h b/BasiliskII/src/include/video_defs.h index c68daeef..a2309d0c 100644 --- a/BasiliskII/src/include/video_defs.h +++ b/BasiliskII/src/include/video_defs.h @@ -108,4 +108,12 @@ enum { // VDTimingInfo struct csTimingFlags = 16 }; +enum { // VDPageInfo struct + csPageMode = 0, + csPageData = 2, + csPagePage = 6, + csPageBaseAddr = 8 + +}; + #endif diff --git a/BasiliskII/src/macos_util.cpp b/BasiliskII/src/macos_util.cpp index f38a8afd..803fed5a 100644 --- a/BasiliskII/src/macos_util.cpp +++ b/BasiliskII/src/macos_util.cpp @@ -20,6 +20,7 @@ #include "sysdeps.h" #include "cpu_emulation.h" +#include "adb.h" #include "main.h" #include "sony.h" #include "disk.h" @@ -101,3 +102,23 @@ void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_s real_size = size - start_byte; } } + + +uint32 DebugUtil(uint32 Selector) +{ + switch (Selector) + { + case duDebuggerGetMax: + return 3; + case duDebuggerEnter: + return 0; + case duDebuggerExit: + return 0; + case duDebuggerPoll: + ADBInterrupt(); + return 0; + default: + return (uint32) paramErr; + } +} + diff --git a/BasiliskII/src/rom_patches.cpp b/BasiliskII/src/rom_patches.cpp index 215fc62b..2fda0d0e 100644 --- a/BasiliskII/src/rom_patches.cpp +++ b/BasiliskII/src/rom_patches.cpp @@ -44,9 +44,10 @@ uint32 PutScrapPatch; // Mac address of PutScrap() patch uint32 ROMBreakpoint = 0; // ROM offset of breakpoint (0 = disabled, 0x2310 = CritError) bool PrintROMInfo = false; // Flag: print ROM information in PatchROM() -static uint32 sony_offset; // ROM offset of .Sony driver -static uint32 serd_offset; // ROM offset of SERD resource (serial drivers) -static uint32 microseconds_offset; // ROM offset of Microseconds() replacement routine +static uint32 sony_offset; // ROM offset of .Sony driver +static uint32 serd_offset; // ROM offset of SERD resource (serial drivers) +static uint32 microseconds_offset; // ROM offset of Microseconds() replacement routine +static uint32 debugutil_offset; // ROM offset of DebugUtil() replacement routine // Prototypes uint16 ROMVersion; @@ -701,6 +702,11 @@ void InstallDrivers(uint32 pb) r.d[0] = 0xa093; Execute68kTrap(0xa247, &r); // SetOSTrapAddress() + // Install DebugUtil() replacement routine + r.a[0] = ROMBaseMac + debugutil_offset; + r.d[0] = 0xa08d; + Execute68kTrap(0xa247, &r); // SetOSTrapAddress() + // Install disk driver r.a[0] = ROMBaseMac + sony_offset + 0x100; r.d[0] = (uint32)DiskRefNum; @@ -930,6 +936,11 @@ static bool patch_rom_classic(void) *wp++ = htons(M68K_RTS); microseconds_offset = (uint8 *)wp - ROMBaseHost; *wp++ = htons(M68K_EMUL_OP_MICROSECONDS); + *wp++ = htons(M68K_RTS); + + // Replace DebugUtil + debugutil_offset = (uint8 *)wp - ROMBaseHost; + *wp++ = htons(M68K_EMUL_OP_DEBUGUTIL); *wp = htons(M68K_RTS); // Replace SCSIDispatch() @@ -1192,18 +1203,19 @@ static bool patch_rom_32(void) *wp = htons(M68K_RTS); // Fake CPU speed test (SetupTimeK) + // *** increased jl : MacsBug uses TimeDBRA for kbd repeat timing wp = (uint16 *)(ROMBaseHost + 0x800); *wp++ = htons(0x31fc); // move.w #xxx,TimeDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0d00); *wp++ = htons(0x31fc); // move.w #xxx,TimeSCCDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0d02); *wp++ = htons(0x31fc); // move.w #xxx,TimeSCSIDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0b24); *wp++ = htons(0x31fc); // move.w #xxx,TimeRAMDBRA - *wp++ = htons(100); + *wp++ = htons(10000); *wp++ = htons(0x0cea); *wp = htons(M68K_RTS); @@ -1215,7 +1227,7 @@ static bool patch_rom_32(void) #endif #if !ROM_IS_WRITE_PROTECTED -#if defined(AMIGA) || defined(__NetBSD__) +#if defined(AMIGA) // Set fake handle at 0x0000 to scratch memory area (so broken Mac programs won't write into Mac ROM) extern uint32 ScratchMem; wp = (uint16 *)(ROMBaseHost + 0xccaa); @@ -1526,6 +1538,11 @@ static bool patch_rom_32(void) *wp++ = htons(M68K_RTS); microseconds_offset = (uint8 *)wp - ROMBaseHost; *wp++ = htons(M68K_EMUL_OP_MICROSECONDS); + *wp++ = htons(M68K_RTS); + + // Replace DebugUtil + debugutil_offset = (uint8 *)wp - ROMBaseHost; + *wp++ = htons(M68K_EMUL_OP_DEBUGUTIL); *wp = htons(M68K_RTS); // Replace SCSIDispatch() diff --git a/BasiliskII/src/video.cpp b/BasiliskII/src/video.cpp index 7fac6739..799844ea 100644 --- a/BasiliskII/src/video.cpp +++ b/BasiliskII/src/video.cpp @@ -244,14 +244,22 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) case cscGetModeTiming: // Get video timing for mode D(bug(" GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode))); - WriteMacInt32(param + csTimingFormat, FOURCC('d','e','c','l')); + WriteMacInt32(param + csTimingFormat, 'decl'); WriteMacInt32(param + csTimingData, 220); // 21" Multiscan WriteMacInt32(param + csTimingFlags, 0x0f); // Mode valid, safe, default and shown in Monitors panel return noErr; case cscGetModeBaseAddress: // Get frame buffer base address D(bug(" GetModeBaseAddress\n")); - WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); + WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); // Base address of video RAM for the current DisplayModeID and relative bit depth + return noErr; + + case cscGetMode: // REQUIRED for MacsBug + D(bug(" GetMode\n")); + WriteMacInt16(param + csPageMode, 0x80); + WriteMacInt32(param + csPageData, 0x80); // Unused + WriteMacInt16(param + csPagePage, 0); // Current display page + WriteMacInt32(param + csPageBaseAddr, VidLocal.desc->mac_frame_base); return noErr; default: