Compare commits
17 commits
main
...
for-m68k-m
| Author | SHA1 | Date | |
|---|---|---|---|
| d44474c24e | |||
| d86ebf1bb8 | |||
| d7d30c5608 | |||
| 831a115881 | |||
| 884330872b | |||
| 5dd8f92ee0 | |||
| ac0ccec3f9 | |||
| f34ec2a1b9 | |||
| 15d0a7b623 | |||
| 19f975ac6c | |||
| b4e41a6739 | |||
| 46c886d9e5 | |||
| cd98358391 | |||
| a59b9fbeb3 | |||
| 24c8b1ebe6 | |||
| b12811d05b | |||
| a16d721ce8 |
16 changed files with 685 additions and 205 deletions
6
Makefile
6
Makefile
|
|
@ -66,7 +66,7 @@ $(MUSASHI)/m68kops.c $(MUSASHI)/m68kops.h:
|
||||||
prepare: $(MUSASHI)/m68kops.c $(MUSASHI)/m68kops.h
|
prepare: $(MUSASHI)/m68kops.c $(MUSASHI)/m68kops.h
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) $(CFLAGS_CFG) -c $< -o $@
|
$(CC) $(CFLAGS) $(CFLAGS_CFG) -c $< -o $@ -MMD -MF $*.d
|
||||||
|
|
||||||
main: $(OBJS)
|
main: $(OBJS)
|
||||||
@echo Linking $(OBJS)
|
@echo Linking $(OBJS)
|
||||||
|
|
@ -74,7 +74,7 @@ main: $(OBJS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make -C $(MUSASHI) clean
|
make -C $(MUSASHI) clean
|
||||||
rm -f $(MY_OBJS) main
|
rm -f $(MY_OBJS) $(OBJS:%.o=%.d) main
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Mac driver sources (no need to generally rebuild
|
# Mac driver sources (no need to generally rebuild
|
||||||
|
|
@ -94,3 +94,5 @@ sonydrv.bin: macsrc/sonydrv.S
|
||||||
cpp $< | $(M68K_AS) -o sonydrv.o
|
cpp $< | $(M68K_AS) -o sonydrv.o
|
||||||
$(M68K_LD) sonydrv.o -o sonydrv.elf -Ttext=0
|
$(M68K_LD) sonydrv.o -o sonydrv.elf -Ttext=0
|
||||||
$(M68K_OBJCOPY) sonydrv.elf -O binary --keep-section=.text $@
|
$(M68K_OBJCOPY) sonydrv.elf -O binary --keep-section=.text $@
|
||||||
|
|
||||||
|
-include $(OBJS:%.o=%.d)
|
||||||
|
|
|
||||||
2
external/Musashi
vendored
2
external/Musashi
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit b3144f12c1296d8fbb600eea13f5db71ffb1b8d8
|
Subproject commit 8dcac80091b745e9181281fbf63cdd04a95b963a
|
||||||
|
|
@ -27,16 +27,21 @@
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
typedef struct disc_desc disc_descr_t;
|
||||||
|
|
||||||
typedef int (*disc_op_read)(void *ctx, uint8_t *data, unsigned int offset, unsigned int len);
|
typedef int (*disc_op_read)(void *ctx, uint8_t *data, unsigned int offset, unsigned int len);
|
||||||
typedef int (*disc_op_write)(void *ctx, uint8_t *data, unsigned int offset, unsigned int len);
|
typedef int (*disc_op_write)(void *ctx, uint8_t *data, unsigned int offset, unsigned int len);
|
||||||
typedef struct {
|
typedef disc_descr_t *(*disc_op_next)(void *ctx);
|
||||||
|
|
||||||
|
struct disc_desc {
|
||||||
uint8_t *base;
|
uint8_t *base;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
int read_only;
|
int read_only;
|
||||||
void *op_ctx;
|
void *op_ctx;
|
||||||
disc_op_read op_read;
|
disc_op_read op_read;
|
||||||
disc_op_write op_write;
|
disc_op_write op_write;
|
||||||
} disc_descr_t;
|
disc_op_next op_next;
|
||||||
|
};
|
||||||
|
|
||||||
#define DISC_NUM_DRIVES 2
|
#define DISC_NUM_DRIVES 2
|
||||||
|
|
||||||
|
|
@ -48,5 +53,5 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
void disc_init(disc_descr_t discs[DISC_NUM_DRIVES]);
|
void disc_init(disc_descr_t discs[DISC_NUM_DRIVES]);
|
||||||
int disc_pv_hook(uint8_t opcode);
|
int disc_pv_hook(uint8_t opcode);
|
||||||
|
void disc_tick();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,10 @@
|
||||||
#define MKC_BackSpace 0x33
|
#define MKC_BackSpace 0x33
|
||||||
#define MKC_Tab 0x30
|
#define MKC_Tab 0x30
|
||||||
|
|
||||||
#define MKC_Left /* 0x46 */ 0x7B
|
#define MKC_Left /* 0x46 */ (0x06 | 0x40)
|
||||||
#define MKC_Right /* 0x42 */ 0x7C
|
#define MKC_Right /* 0x42 */ (0x02 | 0x40)
|
||||||
#define MKC_Down /* 0x48 */ 0x7D
|
#define MKC_Down /* 0x48 */ (0x08 | 0x40)
|
||||||
#define MKC_Up /* 0x4D */ 0x7E
|
#define MKC_Up /* 0x4D */ (0x0d | 0x40)
|
||||||
|
|
||||||
#define MKC_Minus 0x1B
|
#define MKC_Minus 0x1B
|
||||||
#define MKC_Equal 0x18
|
#define MKC_Equal 0x18
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,13 @@
|
||||||
#define M68K_FAST_FUNC(x) __not_in_flash_func(x)
|
#define M68K_FAST_FUNC(x) __not_in_flash_func(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If ON, CPU will support "emul_op" instructions from 0x7100..0x713f by
|
||||||
|
* calling m68k_end_timeslice when they are encountered. The caller can (must)
|
||||||
|
* check the IR register and implement the operation.
|
||||||
|
* If off, these remain illegal instructions.
|
||||||
|
*/
|
||||||
|
#define M68K_EMUL_OP OPT_ON
|
||||||
|
|
||||||
#endif /* M68K_COMPILE_FOR_MAME */
|
#endif /* M68K_COMPILE_FOR_MAME */
|
||||||
|
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#define RAM_HIGH_ADDR 0x600000
|
#define RAM_HIGH_ADDR 0x600000
|
||||||
|
|
||||||
#define PV_SONY_ADDR 0xc00069 /* Magic address for replacement driver PV ops */
|
#define PV_SONY_ADDR 0xc00069 /* Magic address for replacement driver PV ops */
|
||||||
|
#define PV_UART_ADDR 0xc0006A /* Magic address for debug uart */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// RAM accessors
|
// RAM accessors
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ void scc_write(unsigned int address, uint8_t data);
|
||||||
uint8_t scc_read(unsigned int address);
|
uint8_t scc_read(unsigned int address);
|
||||||
/* Set a new state for the DCD pins: */
|
/* Set a new state for the DCD pins: */
|
||||||
void scc_set_dcd(int a, int b);
|
void scc_set_dcd(int a, int b);
|
||||||
|
/* check if scc master interrupt is enabled */
|
||||||
|
int scc_get_mie();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c,
|
0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x6a,
|
||||||
0x00, 0x56, 0x00, 0x68, 0x00, 0x94, 0x05, 0x2e, 0x53, 0x6f, 0x6e, 0x79,
|
0x00, 0x74, 0x00, 0x86, 0x00, 0xb2, 0x05, 0x2e, 0x53, 0x6f, 0x6e, 0x79,
|
||||||
0x48, 0xe7, 0x00, 0xc0, 0x10, 0x3c, 0x00, 0x1e, 0xa7, 0x1e, 0x24, 0x48,
|
0xa0, 0x2f, 0x26, 0x7a, 0x00, 0x9c, 0x16, 0xbc, 0x00, 0x04, 0x48, 0xe7,
|
||||||
0x4c, 0xdf, 0x03, 0x00, 0xb5, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00,
|
0x00, 0xc0, 0x10, 0x3c, 0x00, 0x3c, 0xa7, 0x1e, 0x24, 0x48, 0x4c, 0xdf,
|
||||||
0x00, 0x18, 0x26, 0x7a, 0x00, 0x64, 0x16, 0xbc, 0x00, 0x00, 0x20, 0x3c,
|
0x03, 0x00, 0xb5, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x2c,
|
||||||
0x00, 0x01, 0xff, 0xfb, 0x20, 0x4a, 0x5c, 0x88, 0xa0, 0x4e, 0x4e, 0x75,
|
0x26, 0x7a, 0x00, 0x7a, 0x16, 0xbc, 0x00, 0x00, 0x76, 0x02, 0xd5, 0xfc,
|
||||||
0x70, 0xe9, 0x4e, 0x75, 0x24, 0x7a, 0x00, 0x4a, 0x14, 0xbc, 0x00, 0x01,
|
0x00, 0x00, 0x00, 0x24, 0x20, 0x03, 0x48, 0x40, 0x00, 0x40, 0xff, 0xfb,
|
||||||
0x60, 0x1a, 0x24, 0x7a, 0x00, 0x40, 0x14, 0xbc, 0x00, 0x02, 0x0c, 0x68,
|
0x20, 0x4a, 0xa0, 0x4e, 0x95, 0xfc, 0x00, 0x00, 0x00, 0x1e, 0x53, 0x43,
|
||||||
0x00, 0x01, 0x00, 0x1a, 0x66, 0x0a, 0x4e, 0x75, 0x24, 0x7a, 0x00, 0x2e,
|
0x66, 0x00, 0xff, 0xea, 0x4e, 0x75, 0x70, 0xe9, 0x4e, 0x75, 0x24, 0x7a,
|
||||||
0x14, 0xbc, 0x00, 0x03, 0x32, 0x28, 0x00, 0x06, 0x08, 0x01, 0x00, 0x09,
|
0x00, 0x4c, 0x14, 0xbc, 0x00, 0x01, 0x60, 0x1a, 0x24, 0x7a, 0x00, 0x42,
|
||||||
0x67, 0x0c, 0x4a, 0x40, 0x6f, 0x02, 0x42, 0x40, 0x31, 0x40, 0x00, 0x10,
|
0x14, 0xbc, 0x00, 0x02, 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, 0x66, 0x0a,
|
||||||
0x4e, 0x75, 0x4a, 0x40, 0x6f, 0x04, 0x42, 0x40, 0x4e, 0x75, 0x2f, 0x38,
|
0x4e, 0x75, 0x24, 0x7a, 0x00, 0x30, 0x14, 0xbc, 0x00, 0x03, 0x32, 0x28,
|
||||||
0x08, 0xfc, 0x4e, 0x75, 0x70, 0xe8, 0x4e, 0x75, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x06, 0x08, 0x01, 0x00, 0x09, 0x67, 0x0c, 0x4a, 0x40, 0x6f, 0x02,
|
||||||
|
0x42, 0x40, 0x31, 0x40, 0x00, 0x10, 0x4e, 0x75, 0x4a, 0x40, 0x6f, 0x04,
|
||||||
|
0x42, 0x40, 0x4e, 0x75, 0x2f, 0x38, 0x08, 0xfc, 0x4e, 0x75, 0x70, 0xe8,
|
||||||
|
0x4e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ int umac_loop(void);
|
||||||
void umac_reset(void);
|
void umac_reset(void);
|
||||||
void umac_opt_disassemble(int enable);
|
void umac_opt_disassemble(int enable);
|
||||||
void umac_mouse(int deltax, int deltay, int button);
|
void umac_mouse(int deltax, int deltay, int button);
|
||||||
|
void umac_absmouse(int x, int y, int button);
|
||||||
void umac_kbd_event(uint8_t scancode, int down);
|
void umac_kbd_event(uint8_t scancode, int down);
|
||||||
|
|
||||||
static inline void umac_vsync_event(void)
|
static inline void umac_vsync_event(void)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#define SONY_REF_NUM -5
|
#define SONY_REF_NUM -5
|
||||||
#define SONY_STATUS_SIZE 30
|
#define SONY_STATUS_SIZE 30
|
||||||
|
#define SONY_DRIVE_COUNT 2
|
||||||
|
|
||||||
.org 0
|
.org 0
|
||||||
.globl _start
|
.globl _start
|
||||||
|
|
@ -31,26 +32,41 @@ name:
|
||||||
.byte 5
|
.byte 5
|
||||||
.ascii ".Sony"
|
.ascii ".Sony"
|
||||||
|
|
||||||
|
accrun:
|
||||||
|
.word 0xA02F // PostEvent
|
||||||
|
move.l (faulting_address), %a3
|
||||||
|
move.b #4, (%a3) // Fault! end timeslice
|
||||||
|
|
||||||
open:
|
open:
|
||||||
// Open()
|
// Open()
|
||||||
// Allocate drive status block and pass to Open routine:
|
// Allocate drive status block and pass to Open routine:
|
||||||
movem.l %a0-%a1, -(%sp)
|
movem.l %a0-%a1, -(%sp)
|
||||||
move.b #SONY_STATUS_SIZE, %d0
|
move.b #SONY_STATUS_SIZE*SONY_DRIVE_COUNT, %d0
|
||||||
.word 0xa71e // NewPtrSysClear
|
.word 0xa71e // NewPtrSysClear
|
||||||
move.l %a0, %a2
|
move.l %a0, %a2
|
||||||
movem.l (%sp)+, %a0-%a1
|
movem.l (%sp)+, %a0-%a1
|
||||||
cmp.l #0, %a2
|
cmp.l #0, %a2
|
||||||
beq 2f // lolfail
|
beq 2f // lolfail
|
||||||
|
|
||||||
|
|
||||||
move.l (faulting_address), %a3
|
move.l (faulting_address), %a3
|
||||||
move.b #0, (%a3) // Fault! Open: op 0
|
move.b #0, (%a3) // Fault! Open: op 0
|
||||||
|
|
||||||
// FIXME: Support variable number of drives
|
// Now add the drives:
|
||||||
// Now add the drive:
|
mov.l #SONY_DRIVE_COUNT, %d3
|
||||||
move.l #(0x00010000 + (0xffff & SONY_REF_NUM)), %d0
|
add.l #6+SONY_STATUS_SIZE*(SONY_DRIVE_COUNT-1), %a2
|
||||||
|
|
||||||
|
3:
|
||||||
|
move.l %d3, %d0
|
||||||
|
swap %d0 // refnum in top half of d0, lower is 0000
|
||||||
|
ori.w #(0xffff & SONY_REF_NUM), %d0 // index & refnum in d0
|
||||||
move.l %a2, %a0
|
move.l %a2, %a0
|
||||||
add.l #6, %a0
|
|
||||||
.word 0xa04e // AddDrive
|
.word 0xa04e // AddDrive
|
||||||
|
|
||||||
|
sub.l #SONY_STATUS_SIZE, %a2 // next drive on next iteration
|
||||||
|
subq #1, %d3
|
||||||
|
bne 3b // more drives to add?
|
||||||
|
|
||||||
1: rts
|
1: rts
|
||||||
2: moveq #-23, %d0
|
2: moveq #-23, %d0
|
||||||
rts
|
rts
|
||||||
|
|
|
||||||
116
src/disc.c
116
src/disc.c
|
|
@ -16,6 +16,7 @@
|
||||||
#include "m68k.h"
|
#include "m68k.h"
|
||||||
#include "machw.h"
|
#include "machw.h"
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define DDBG(...) printf(__VA_ARGS__)
|
#define DDBG(...) printf(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
|
@ -26,6 +27,8 @@
|
||||||
|
|
||||||
extern void umac_disc_ejected(void);
|
extern void umac_disc_ejected(void);
|
||||||
|
|
||||||
|
static uint8_t accrun_flag;
|
||||||
|
|
||||||
// B2 decls:
|
// B2 decls:
|
||||||
static int16_t SonyOpen(uint32_t pb, uint32_t dce, uint32_t status);
|
static int16_t SonyOpen(uint32_t pb, uint32_t dce, uint32_t status);
|
||||||
static int16_t SonyPrime(uint32_t pb, uint32_t dce);
|
static int16_t SonyPrime(uint32_t pb, uint32_t dce);
|
||||||
|
|
@ -66,6 +69,10 @@ int disc_pv_hook(uint8_t opcode)
|
||||||
DDBG("[Disc: STATUS]\n");
|
DDBG("[Disc: STATUS]\n");
|
||||||
d0 = SonyStatus(ADR24(a0), ADR24(a1));
|
d0 = SonyStatus(ADR24(a0), ADR24(a1));
|
||||||
break;
|
break;
|
||||||
|
case 4: // upcall helper
|
||||||
|
DDBG("[Disc: end timeslice]\n");
|
||||||
|
m68k_end_timeslice();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DERR("[Disc PV op %02x unhandled!]\n", opcode);
|
DERR("[Disc PV op %02x unhandled!]\n", opcode);
|
||||||
|
|
@ -138,6 +145,7 @@ typedef struct sony_drive_info {
|
||||||
void *op_ctx;
|
void *op_ctx;
|
||||||
disc_op_read op_read; // Callback for read (when data == 0)
|
disc_op_read op_read; // Callback for read (when data == 0)
|
||||||
disc_op_write op_write; // '' '' write ''
|
disc_op_write op_write; // '' '' write ''
|
||||||
|
disc_op_next op_next; // Callback for mount next disc
|
||||||
} sony_drinfo_t;
|
} sony_drinfo_t;
|
||||||
|
|
||||||
// List of drives handled by this driver
|
// List of drives handled by this driver
|
||||||
|
|
@ -160,17 +168,24 @@ static sony_drinfo_t *get_drive_info(int num)
|
||||||
* Initialization
|
* Initialization
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void SonyInit(disc_descr_t discs[DISC_NUM_DRIVES])
|
static void SonyInit1(sony_drinfo_t *drive, disc_descr_t *disc)
|
||||||
{
|
{
|
||||||
drives[0].num = 0;
|
drive->to_be_mounted = 1;
|
||||||
drives[0].to_be_mounted = 1;
|
drive->read_only = disc->read_only;
|
||||||
drives[0].read_only = discs[0].read_only;
|
drive->data = disc->base;
|
||||||
drives[0].data = discs[0].base;
|
drive->size = disc->size;
|
||||||
drives[0].size = discs[0].size;
|
drive->op_ctx = disc->op_ctx;
|
||||||
drives[0].op_ctx = discs[0].op_ctx;
|
drive->op_read = disc->op_read;
|
||||||
drives[0].op_read = discs[0].op_read;
|
drive->op_write = disc->op_write;
|
||||||
drives[0].op_write = discs[0].op_write;
|
drive->op_next = disc->op_next;
|
||||||
// FIXME: Disc 2
|
}
|
||||||
|
|
||||||
|
static void SonyInit(disc_descr_t discs[DISC_NUM_DRIVES])
|
||||||
|
{
|
||||||
|
for(int i = 0; i < DISC_NUM_DRIVES; i++) {
|
||||||
|
drives[i].num = 0; // set in SonyOpen
|
||||||
|
SonyInit1(&drives[i], &discs[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -227,19 +242,20 @@ int16_t SonyOpen(uint32_t pb, uint32_t dce, uint32_t status)
|
||||||
set_dsk_err(0);
|
set_dsk_err(0);
|
||||||
|
|
||||||
// Install drives
|
// Install drives
|
||||||
//for (int drnum = 0; drnum < NUM_DRIVES; drnum++) {
|
int free_drive_number = 1;
|
||||||
const int drnum = 0;
|
for (int drnum = 0; drnum < DISC_NUM_DRIVES; drnum++) {
|
||||||
sony_drinfo_t *info = &drives[drnum];
|
sony_drinfo_t *info = &drives[drnum];
|
||||||
|
|
||||||
info->num = FindFreeDriveNumber(1); // ? 1 for internal, 2 for external
|
info->num = FindFreeDriveNumber(free_drive_number); // ? 1 for internal, 2 for external
|
||||||
|
free_drive_number = info->num + 1;
|
||||||
info->to_be_mounted = 0;
|
info->to_be_mounted = 0;
|
||||||
|
|
||||||
// Original code allocated drive status record here (invoked
|
// Original code allocated drive status record here (invoked
|
||||||
// trap to NewPtrSysClear), but our driver does this instead
|
// trap to NewPtrSysClear), but our driver does this instead
|
||||||
// (it's passed in via status parameter), to avoid having to
|
// (it's passed in via status parameter), to avoid having to
|
||||||
// implement invocation of 68K traps/upcalls from sim env.
|
// implement invocation of 68K traps/upcalls from sim env.
|
||||||
info->status = status;
|
info->status = status + 30 * drnum;
|
||||||
DDBG(" DrvSts at %08x\n", info->status);
|
DDBG(" DrvSts at %08x gets drnum %d num %d\n", info->status, drnum, info->num);
|
||||||
|
|
||||||
// Set up drive status
|
// Set up drive status
|
||||||
// ME: do 800K, double sided (see IM)
|
// ME: do 800K, double sided (see IM)
|
||||||
|
|
@ -253,12 +269,17 @@ int16_t SonyOpen(uint32_t pb, uint32_t dce, uint32_t status)
|
||||||
//WriteMacInt8(info->status + dsTwoMegFmt, 0xff); // 1.44MB (0 = 720K)
|
//WriteMacInt8(info->status + dsTwoMegFmt, 0xff); // 1.44MB (0 = 720K)
|
||||||
|
|
||||||
// If disk in drive...
|
// If disk in drive...
|
||||||
|
if (info->size) {
|
||||||
|
if (drnum == 0)
|
||||||
WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
|
WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
|
||||||
|
else
|
||||||
|
info->to_be_mounted = 1;
|
||||||
WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
|
WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
|
||||||
DDBG(" disk inserted, flagging for mount\n");
|
DDBG(" disk inserted, flagging for mount\n");
|
||||||
info->to_be_mounted = 1;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Original code ddded drive to drive queue here (invoked trap
|
// Original code added drive to drive queue here (invoked trap
|
||||||
// to AddDrive), but our driver does this after this PV call returns.
|
// to AddDrive), but our driver does this after this PV call returns.
|
||||||
// FIXME: In future return a bitmap of drives to add.
|
// FIXME: In future return a bitmap of drives to add.
|
||||||
(void)pb;
|
(void)pb;
|
||||||
|
|
@ -369,14 +390,8 @@ int16_t SonyControl(uint32_t pb, uint32_t dce)
|
||||||
return set_dsk_err(noErr);
|
return set_dsk_err(noErr);
|
||||||
|
|
||||||
case 65: { // Periodic action (accRun, "insert" disks on startup)
|
case 65: { // Periodic action (accRun, "insert" disks on startup)
|
||||||
static int complained_yet = 0;
|
accrun_flag = 1;
|
||||||
if (!complained_yet) {
|
return set_dsk_err(noErr);
|
||||||
DERR("SonyControl:accRun: Not supported!\n");
|
|
||||||
complained_yet = 1;
|
|
||||||
}
|
|
||||||
// The original emulation code hooked this to mount_mountable_volumes,
|
|
||||||
// which called back to PostEvent(diskEvent).
|
|
||||||
return set_dsk_err(-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -411,8 +426,16 @@ int16_t SonyControl(uint32_t pb, uint32_t dce)
|
||||||
// SysEject(info->fh);
|
// SysEject(info->fh);
|
||||||
WriteMacInt8(info->status + dsDiskInPlace, 0);
|
WriteMacInt8(info->status + dsDiskInPlace, 0);
|
||||||
|
|
||||||
|
if(info->num == 1)
|
||||||
umac_disc_ejected();
|
umac_disc_ejected();
|
||||||
}
|
}
|
||||||
|
if(info->op_next) {
|
||||||
|
DERR("DISC: mount new\n");
|
||||||
|
disc_descr_t *new_disc = info->op_next(info->op_ctx);
|
||||||
|
if (new_disc) {
|
||||||
|
SonyInit1(info, new_disc);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8: // Set tag buffer (ignore, not supported)
|
case 8: // Set tag buffer (ignore, not supported)
|
||||||
|
|
@ -534,3 +557,46 @@ int16_t SonyStatus(uint32_t pb, uint32_t dce)
|
||||||
|
|
||||||
return set_dsk_err(err);
|
return set_dsk_err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define M68K_REG_LAST (M68K_REG_CPU_TYPE)
|
||||||
|
|
||||||
|
static int PostEvent(int type, int num) {
|
||||||
|
DDBG("PostEvent EventCode=%d EventMsg=%d\n", type, num);
|
||||||
|
uint32_t regs[M68K_REG_LAST];
|
||||||
|
for(int i=0; i<M68K_REG_LAST; i++)
|
||||||
|
regs[i] = m68k_get_reg(NULL, i);
|
||||||
|
m68k_set_reg(M68K_REG_D0, num);
|
||||||
|
m68k_set_reg(M68K_REG_A0, type);
|
||||||
|
uint32_t new_sp = regs[M68K_REG_SP] - 4;
|
||||||
|
cpu_write_word(new_sp, 0xA02F); // PostEvent
|
||||||
|
cpu_write_word(new_sp+2, 0x7180); // emul_ret
|
||||||
|
m68k_set_reg(M68K_REG_PC, new_sp); // PostEvent
|
||||||
|
m68k_set_reg(M68K_REG_SP, new_sp); // Emul_Ret
|
||||||
|
int used = m68k_execute(80000);
|
||||||
|
int result = m68k_get_reg(NULL, M68K_REG_D0);
|
||||||
|
if (used >= 20000 || m68k_get_reg(NULL, M68K_REG_PC) != new_sp + 4 ||
|
||||||
|
m68k_get_reg(NULL, M68K_REG_SP) != new_sp) {
|
||||||
|
DERR("trap call didn't seem to work. used=%d PC=%08x (expected %08x) SP=%08x (expected %08x)\n",
|
||||||
|
used,
|
||||||
|
m68k_get_reg(NULL, M68K_REG_PC), new_sp+4,
|
||||||
|
m68k_get_reg(NULL, M68K_REG_SP), new_sp);
|
||||||
|
result = 1; // some kind of failure (but you're probably doomed)
|
||||||
|
}
|
||||||
|
for(int i=0; i<M68K_REG_LAST; i++)
|
||||||
|
m68k_set_reg(i, regs[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disc_tick() {
|
||||||
|
if (!accrun_flag) return;
|
||||||
|
for (int i = 0; i < DISC_NUM_DRIVES; i++) {
|
||||||
|
sony_drinfo_t *info = &drives[i];
|
||||||
|
if (drives[i].to_be_mounted) {
|
||||||
|
int inPlace = ReadMacInt8(info->status + dsDiskInPlace); // Inserted removable disk
|
||||||
|
if (inPlace || PostEvent(7, drives[i].num) == 0) {
|
||||||
|
drives[i].to_be_mounted = 0;
|
||||||
|
WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
161
src/main.c
161
src/main.c
|
|
@ -46,6 +46,7 @@
|
||||||
#include "scc.h"
|
#include "scc.h"
|
||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
#include "disc.h"
|
#include "disc.h"
|
||||||
|
#include "ringbuf.h"
|
||||||
|
|
||||||
#ifdef PICO
|
#ifdef PICO
|
||||||
#include "pico.h"
|
#include "pico.h"
|
||||||
|
|
@ -81,6 +82,8 @@ static int disassemble = 0;
|
||||||
|
|
||||||
static void update_overlay_layout(void);
|
static void update_overlay_layout(void);
|
||||||
|
|
||||||
|
extern int pv_uart_read();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static int m68k_dump_regs(char *buf, int len)
|
static int m68k_dump_regs(char *buf, int len)
|
||||||
|
|
@ -209,6 +212,7 @@ static uint8_t via_rb_in(void)
|
||||||
*/
|
*/
|
||||||
#define KBD_CMD_GET_MODEL 0x16
|
#define KBD_CMD_GET_MODEL 0x16
|
||||||
#define KBD_CMD_INQUIRY 0x10
|
#define KBD_CMD_INQUIRY 0x10
|
||||||
|
#define KBD_CMD_INSTANT 0x14
|
||||||
#define KBD_MODEL 5
|
#define KBD_MODEL 5
|
||||||
#define KBD_RSP_NULL 0x7b
|
#define KBD_RSP_NULL 0x7b
|
||||||
|
|
||||||
|
|
@ -225,7 +229,9 @@ static void via_sr_tx(uint8_t data)
|
||||||
kbd_last_cmd_time = global_time_us;
|
kbd_last_cmd_time = global_time_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kbd_pending_evt = -1;
|
uint8_t kbd_pending_evt_array[32];
|
||||||
|
ringbuf_t kbd_pending_evt = {kbd_pending_evt_array, sizeof(kbd_pending_evt_array), 0, 0};
|
||||||
|
|
||||||
/* Emulate the keyboard: receive commands (such as an inquiry, polling
|
/* Emulate the keyboard: receive commands (such as an inquiry, polling
|
||||||
* for keypresses) and respond using via_sr_rx().
|
* for keypresses) and respond using via_sr_rx().
|
||||||
*/
|
*/
|
||||||
|
|
@ -236,12 +242,14 @@ static void kbd_rx(uint8_t data)
|
||||||
case KBD_CMD_GET_MODEL:
|
case KBD_CMD_GET_MODEL:
|
||||||
via_sr_rx(0x01 | (KBD_MODEL << 1));
|
via_sr_rx(0x01 | (KBD_MODEL << 1));
|
||||||
break;
|
break;
|
||||||
|
case KBD_CMD_INSTANT:
|
||||||
case KBD_CMD_INQUIRY:
|
case KBD_CMD_INQUIRY:
|
||||||
if (kbd_pending_evt == -1) {
|
{
|
||||||
via_sr_rx(KBD_RSP_NULL);
|
int evt = KBD_RSP_NULL;
|
||||||
} else {
|
if (ringbuf_avail(&kbd_pending_evt)) {
|
||||||
via_sr_rx(kbd_pending_evt);
|
evt = ringbuf_get(&kbd_pending_evt);
|
||||||
kbd_pending_evt = -1;
|
}
|
||||||
|
via_sr_rx(evt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -267,12 +275,18 @@ static void kbd_check_work(void)
|
||||||
|
|
||||||
void umac_kbd_event(uint8_t scancode, int down)
|
void umac_kbd_event(uint8_t scancode, int down)
|
||||||
{
|
{
|
||||||
if (kbd_pending_evt >= 0) {
|
int result = 0;
|
||||||
MDBG("KBD: Received event %02x with event %02x pending!\n",
|
if (scancode & 0x80) {
|
||||||
scancode, kbd_pending_evt);
|
result = ringbuf_put(&kbd_pending_evt, 0x79);
|
||||||
/* FIXME: Add a queue */
|
scancode &= ~0x80;
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
result = ringbuf_put(&kbd_pending_evt, scancode | (down ? 0 : 0x80));
|
||||||
|
}
|
||||||
|
if (result < 0) {
|
||||||
|
MERR("KBD: Received event %02x with full queue. Event discarded.\n",
|
||||||
|
scancode);
|
||||||
}
|
}
|
||||||
kbd_pending_evt = scancode | (down ? 0 : 0x80);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VIA IRQ output hook:
|
// VIA IRQ output hook:
|
||||||
|
|
@ -388,6 +402,10 @@ unsigned int FAST_FUNC(cpu_read_word)(unsigned int address)
|
||||||
if (IS_ROM(address))
|
if (IS_ROM(address))
|
||||||
return ROM_RD16(address & (ROM_SIZE - 1));
|
return ROM_RD16(address & (ROM_SIZE - 1));
|
||||||
|
|
||||||
|
if (address == PV_UART_ADDR) {
|
||||||
|
return pv_uart_read();
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_TESTSW(address))
|
if (IS_TESTSW(address))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -462,6 +480,11 @@ void FAST_FUNC(cpu_write_byte)(unsigned int address, unsigned int value)
|
||||||
exit_error("Disc PV hook failed (%02x)", value);
|
exit_error("Disc PV hook failed (%02x)", value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (address == PV_UART_ADDR) {
|
||||||
|
putchar(value);
|
||||||
|
fflush(stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
printf("Ignoring write %02x to address %08x\n", value&0xff, address);
|
printf("Ignoring write %02x to address %08x\n", value&0xff, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -592,10 +615,35 @@ void umac_opt_disassemble(int enable)
|
||||||
disassemble = enable;
|
disassemble = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MOUSE_MAX_PENDING_PIX 30
|
/* Provide mouse input (movement, button) data.
|
||||||
|
*
|
||||||
|
* X is positive going right; Y is positive going upwards.
|
||||||
|
*/
|
||||||
|
void umac_absmouse(int x, int y, int button)
|
||||||
|
{
|
||||||
|
if (!scc_get_mie()) return;
|
||||||
|
#define MTemp_h 0x82a
|
||||||
|
#define MTemp_v 0x828
|
||||||
|
#define CrsrNew 0x8ce
|
||||||
|
#define CrsrCouple 0x8cf
|
||||||
|
|
||||||
static int pending_mouse_deltax = 0;
|
int oldx = RAM_RD16(MTemp_h);
|
||||||
static int pending_mouse_deltay = 0;
|
int oldy = RAM_RD16(MTemp_v);
|
||||||
|
|
||||||
|
if(x != oldx) {
|
||||||
|
RAM_WR16(MTemp_h, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y != oldy) {
|
||||||
|
RAM_WR16(MTemp_v, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(x != oldx || y != oldy) {
|
||||||
|
RAM_WR8(CrsrNew, RAM_RD8(CrsrCouple));
|
||||||
|
}
|
||||||
|
|
||||||
|
via_mouse_pressed = button;
|
||||||
|
}
|
||||||
|
|
||||||
/* Provide mouse input (movement, button) data.
|
/* Provide mouse input (movement, button) data.
|
||||||
*
|
*
|
||||||
|
|
@ -603,83 +651,22 @@ static int pending_mouse_deltay = 0;
|
||||||
*/
|
*/
|
||||||
void umac_mouse(int deltax, int deltay, int button)
|
void umac_mouse(int deltax, int deltay, int button)
|
||||||
{
|
{
|
||||||
pending_mouse_deltax += deltax;
|
if (!scc_get_mie()) return;
|
||||||
pending_mouse_deltay += deltay;
|
if(deltax) {
|
||||||
|
int16_t temp_h = RAM_RD16(MTemp_h) + deltax;
|
||||||
/* Clamp if the UI has flooded with lots and lots of steps!
|
RAM_WR16(MTemp_h, temp_h);
|
||||||
*/
|
|
||||||
if (pending_mouse_deltax > MOUSE_MAX_PENDING_PIX)
|
|
||||||
pending_mouse_deltax = MOUSE_MAX_PENDING_PIX;
|
|
||||||
if (pending_mouse_deltax < -MOUSE_MAX_PENDING_PIX)
|
|
||||||
pending_mouse_deltax = -MOUSE_MAX_PENDING_PIX;
|
|
||||||
if (pending_mouse_deltay > MOUSE_MAX_PENDING_PIX)
|
|
||||||
pending_mouse_deltay = MOUSE_MAX_PENDING_PIX;
|
|
||||||
if (pending_mouse_deltay < -MOUSE_MAX_PENDING_PIX)
|
|
||||||
pending_mouse_deltay = -MOUSE_MAX_PENDING_PIX;
|
|
||||||
|
|
||||||
/* FIXME: The movement might take a little time, but this
|
|
||||||
* posts the button status immediately. Probably OK, but the
|
|
||||||
* mismatch might be perceptible.
|
|
||||||
*/
|
|
||||||
via_mouse_pressed = button;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mouse_tick(void)
|
|
||||||
{
|
|
||||||
/* Periodically, check if the mouse X/Y deltas are non-zero.
|
|
||||||
* If a movement is required, encode one step in X and/or Y
|
|
||||||
* and deduct from the pending delta.
|
|
||||||
*
|
|
||||||
* The step ultimately posts an SCC IRQ, so we _don't_ try to
|
|
||||||
* make any more steps while an IRQ is currently pending.
|
|
||||||
* (Currently, that means a previous step's DCD IRQ event
|
|
||||||
* hasn't yet been consumed by the OS handler. In future, if
|
|
||||||
* SCC is extended with other IRQ types, then just checking
|
|
||||||
* the IRQ status is technically too crude, but should still
|
|
||||||
* be fine given the timeframes.)
|
|
||||||
*/
|
|
||||||
if (pending_mouse_deltax == 0 && pending_mouse_deltay == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (scc_irq_state == 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
static int old_dcd_a = 0;
|
|
||||||
static int old_dcd_b = 0;
|
|
||||||
|
|
||||||
/* Mouse X/Y quadrature signals are wired to:
|
|
||||||
* VIA Port B[4] & SCC DCD_A for X
|
|
||||||
* VIA Port B[5] & SCC DCD_B for Y
|
|
||||||
*
|
|
||||||
* As VIA mouse signals aren't sampled until IRQ, can do this
|
|
||||||
* in one step, toggling existing DCD states and setting VIA
|
|
||||||
* either equal or opposite to DCD:
|
|
||||||
*/
|
|
||||||
int dcd_a = old_dcd_a;
|
|
||||||
int dcd_b = old_dcd_b;
|
|
||||||
int deltax = pending_mouse_deltax;
|
|
||||||
int deltay = pending_mouse_deltay;
|
|
||||||
uint8_t qb = via_quadbits;
|
|
||||||
|
|
||||||
if (deltax) {
|
|
||||||
dcd_a = !dcd_a;
|
|
||||||
qb = (qb & ~0x10) | ((deltax < 0) == dcd_a ? 0x10 : 0);
|
|
||||||
pending_mouse_deltax += (deltax > 0) ? -1 : 1;
|
|
||||||
MDBG(" px %d, oldpx %d", pending_mouse_deltax, deltax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deltay) {
|
if (deltay) {
|
||||||
dcd_b = !dcd_b;
|
int16_t temp_v = RAM_RD16(MTemp_v) - deltay;
|
||||||
qb = (qb & ~0x20) | ((deltay < 0) == dcd_b ? 0x20 : 0);
|
RAM_WR16(MTemp_v, temp_v);
|
||||||
pending_mouse_deltay += (deltay > 0) ? -1 : 1;
|
|
||||||
MDBG(" py %d, oldpy %d", pending_mouse_deltay, deltay);
|
|
||||||
}
|
}
|
||||||
MDBG("\n");
|
|
||||||
|
|
||||||
via_quadbits = qb;
|
if(deltax || deltay) {
|
||||||
old_dcd_a = dcd_a;
|
RAM_WR8(CrsrNew, RAM_RD8(CrsrCouple));
|
||||||
old_dcd_b = dcd_b;
|
}
|
||||||
scc_set_dcd(dcd_a, dcd_b);
|
|
||||||
|
via_mouse_pressed = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
void umac_reset(void)
|
void umac_reset(void)
|
||||||
|
|
@ -711,7 +698,7 @@ int umac_loop(void)
|
||||||
|
|
||||||
// Device polling
|
// Device polling
|
||||||
via_tick(global_time_us);
|
via_tick(global_time_us);
|
||||||
mouse_tick();
|
disc_tick();
|
||||||
kbd_check_work();
|
kbd_check_work();
|
||||||
|
|
||||||
return sim_done;
|
return sim_done;
|
||||||
|
|
|
||||||
98
src/ringbuf.c
Normal file
98
src/ringbuf.c
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Jim Mussared
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ringbuf.h"
|
||||||
|
|
||||||
|
int ringbuf_get16(ringbuf_t *r) {
|
||||||
|
int v = ringbuf_peek16(r);
|
||||||
|
if (v == -1) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
r->iget += 2;
|
||||||
|
if (r->iget >= r->size) {
|
||||||
|
r->iget -= r->size;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ringbuf_peek16(ringbuf_t *r) {
|
||||||
|
if (r->iget == r->iput) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t iget_a = r->iget + 1;
|
||||||
|
if (iget_a == r->size) {
|
||||||
|
iget_a = 0;
|
||||||
|
}
|
||||||
|
if (iget_a == r->iput) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (r->buf[r->iget] << 8) | (r->buf[iget_a]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ringbuf_put16(ringbuf_t *r, uint16_t v) {
|
||||||
|
uint32_t iput_a = r->iput + 1;
|
||||||
|
if (iput_a == r->size) {
|
||||||
|
iput_a = 0;
|
||||||
|
}
|
||||||
|
if (iput_a == r->iget) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t iput_b = iput_a + 1;
|
||||||
|
if (iput_b == r->size) {
|
||||||
|
iput_b = 0;
|
||||||
|
}
|
||||||
|
if (iput_b == r->iget) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
r->buf[r->iput] = (v >> 8) & 0xff;
|
||||||
|
r->buf[iput_a] = v & 0xff;
|
||||||
|
r->iput = iput_b;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns:
|
||||||
|
// 0: Success
|
||||||
|
// -1: Not enough data available to complete read (try again later)
|
||||||
|
// -2: Requested read is larger than buffer - will never succeed
|
||||||
|
int ringbuf_get_bytes(ringbuf_t *r, uint8_t *data, size_t data_len) {
|
||||||
|
if (ringbuf_avail(r) < data_len) {
|
||||||
|
return (r->size <= data_len) ? -2 : -1;
|
||||||
|
}
|
||||||
|
ringbuf_memcpy_get_internal(r, data, data_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns:
|
||||||
|
// 0: Success
|
||||||
|
// -1: Not enough free space available to complete write (try again later)
|
||||||
|
// -2: Requested write is larger than buffer - will never succeed
|
||||||
|
int ringbuf_put_bytes(ringbuf_t *r, const uint8_t *data, size_t data_len) {
|
||||||
|
if (ringbuf_free(r) < data_len) {
|
||||||
|
return (r->size <= data_len) ? -2 : -1;
|
||||||
|
}
|
||||||
|
ringbuf_memcpy_put_internal(r, data, data_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
131
src/ringbuf.h
Normal file
131
src/ringbuf.h
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Paul Sokolovsky
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef MICROPY_INCLUDED_PY_RINGBUF_H
|
||||||
|
#define MICROPY_INCLUDED_PY_RINGBUF_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct _ringbuf_t {
|
||||||
|
uint8_t *buf;
|
||||||
|
uint16_t size;
|
||||||
|
uint16_t iget;
|
||||||
|
uint16_t iput;
|
||||||
|
} ringbuf_t;
|
||||||
|
|
||||||
|
// Static initialization:
|
||||||
|
// byte buf_array[N];
|
||||||
|
// ringbuf_t buf = {buf_array, sizeof(buf_array)};
|
||||||
|
|
||||||
|
// Dynamic initialization. This needs to become findable as a root pointer!
|
||||||
|
#define ringbuf_alloc(r, sz) \
|
||||||
|
{ \
|
||||||
|
(r)->buf = m_new(uint8_t, sz); \
|
||||||
|
(r)->size = sz; \
|
||||||
|
(r)->iget = (r)->iput = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ringbuf_get(ringbuf_t *r) {
|
||||||
|
if (r->iget == r->iput) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint8_t v = r->buf[r->iget++];
|
||||||
|
if (r->iget >= r->size) {
|
||||||
|
r->iget = 0;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ringbuf_peek(ringbuf_t *r) {
|
||||||
|
if (r->iget == r->iput) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return r->buf[r->iget];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ringbuf_put(ringbuf_t *r, uint8_t v) {
|
||||||
|
uint32_t iput_new = r->iput + 1;
|
||||||
|
if (iput_new >= r->size) {
|
||||||
|
iput_new = 0;
|
||||||
|
}
|
||||||
|
if (iput_new == r->iget) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
r->buf[r->iput] = v;
|
||||||
|
r->iput = iput_new;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t ringbuf_free(ringbuf_t *r) {
|
||||||
|
return (r->size + r->iget - r->iput - 1) % r->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t ringbuf_avail(ringbuf_t *r) {
|
||||||
|
return (r->size + r->iput - r->iget) % r->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ringbuf_memcpy_get_internal(ringbuf_t *r, uint8_t *data, size_t data_len) {
|
||||||
|
// No bounds / space checking is performed here so ensure available size is checked before running this
|
||||||
|
// otherwise data loss or buffer overflow can occur.
|
||||||
|
uint32_t iget = r->iget;
|
||||||
|
uint32_t iget_a = (iget + data_len) % r->size;
|
||||||
|
uint8_t *datap = data;
|
||||||
|
if (iget_a < iget) {
|
||||||
|
// Copy part of the data from the space left at the end of the buffer
|
||||||
|
memcpy(datap, r->buf + iget, r->size - iget);
|
||||||
|
datap += (r->size - iget);
|
||||||
|
iget = 0;
|
||||||
|
}
|
||||||
|
memcpy(datap, r->buf + iget, iget_a - iget);
|
||||||
|
r->iget = iget_a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ringbuf_memcpy_put_internal(ringbuf_t *r, const uint8_t *data, size_t data_len) {
|
||||||
|
// No bounds / space checking is performed here so ensure free size is checked before running this
|
||||||
|
// otherwise data loss or buffer overflow can occur.
|
||||||
|
uint32_t iput = r->iput;
|
||||||
|
uint32_t iput_a = (iput + data_len) % r->size;
|
||||||
|
const uint8_t *datap = data;
|
||||||
|
if (iput_a < iput) {
|
||||||
|
// Copy part of the data to the end of the buffer
|
||||||
|
memcpy(r->buf + iput, datap, r->size - iput);
|
||||||
|
datap += (r->size - iput);
|
||||||
|
iput = 0;
|
||||||
|
}
|
||||||
|
memcpy(r->buf + iput, datap, iput_a - iput);
|
||||||
|
r->iput = iput_a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: big-endian. No-op if not enough room available for both bytes.
|
||||||
|
int ringbuf_get16(ringbuf_t *r);
|
||||||
|
int ringbuf_peek16(ringbuf_t *r);
|
||||||
|
int ringbuf_put16(ringbuf_t *r, uint16_t v);
|
||||||
|
|
||||||
|
int ringbuf_get_bytes(ringbuf_t *r, uint8_t *data, size_t data_len);
|
||||||
|
int ringbuf_put_bytes(ringbuf_t *r, const uint8_t *data, size_t data_len);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_PY_RINGBUF_H
|
||||||
|
|
@ -126,6 +126,8 @@ static void scc_wr3(int AnB, uint8_t data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int scc_get_mie() { return scc_mie; }
|
||||||
|
|
||||||
// WR9: Master Interrupt control and reset commands
|
// WR9: Master Interrupt control and reset commands
|
||||||
static void scc_wr9(uint8_t data)
|
static void scc_wr9(uint8_t data)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
241
src/unix_main.c
241
src/unix_main.c
|
|
@ -28,6 +28,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
@ -49,7 +51,7 @@ static void print_help(char *n)
|
||||||
printf("Syntax: %s <options>\n"
|
printf("Syntax: %s <options>\n"
|
||||||
"\t-r <rom path>\t\tDefault 'rom.bin'\n"
|
"\t-r <rom path>\t\tDefault 'rom.bin'\n"
|
||||||
"\t-W <rom dump path>\tDump ROM after patching\n"
|
"\t-W <rom dump path>\tDump ROM after patching\n"
|
||||||
"\t-d <disc path>\n"
|
"\t-d <disc path> (may be repeated)\n"
|
||||||
"\t-w\t\t\tEnable persistent disc writes (default R/O)\n"
|
"\t-w\t\t\tEnable persistent disc writes (default R/O)\n"
|
||||||
"\t-i\t\t\tDisassembled instruction trace\n", n);
|
"\t-i\t\t\tDisassembled instruction trace\n", n);
|
||||||
}
|
}
|
||||||
|
|
@ -78,6 +80,159 @@ static void copy_fb(uint32_t *fb_out, uint8_t *fb_in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
disc_descr_t *desc;
|
||||||
|
int opt_write;
|
||||||
|
int slot;
|
||||||
|
int idx, num_names;
|
||||||
|
char **names;
|
||||||
|
} unix_disc_descr_t;
|
||||||
|
|
||||||
|
static int open_disc_single(unix_disc_descr_t *desc, int slot, int opt_write, const char *disc_filename) {
|
||||||
|
int ofd;
|
||||||
|
void *disc_base;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
printf("Opening disc '%s'\n", disc_filename);
|
||||||
|
|
||||||
|
ofd = open(disc_filename, opt_write ? O_RDWR : O_RDONLY);
|
||||||
|
if (ofd < 0) {
|
||||||
|
perror("Disc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fstat(ofd, &sb);
|
||||||
|
size_t disc_size = sb.st_size;
|
||||||
|
|
||||||
|
/* Discs are always _writable_ from the perspective of
|
||||||
|
* the Mac, but by default data is a MAP_PRIVATE copy
|
||||||
|
* and is not synchronised to the backing file. If
|
||||||
|
* opt_write, we use MAP_SHARED and open the file RW,
|
||||||
|
* so writes persist to the disc image.
|
||||||
|
*/
|
||||||
|
disc_base = mmap(0, disc_size, PROT_READ | PROT_WRITE,
|
||||||
|
opt_write ? MAP_SHARED : MAP_PRIVATE,
|
||||||
|
ofd, 0);
|
||||||
|
close(ofd);
|
||||||
|
if (disc_base == MAP_FAILED) {
|
||||||
|
printf("Can't mmap disc!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("Disc mapped at %p, slot %d, size %ld\n", (void *)disc_base, slot, disc_size);
|
||||||
|
|
||||||
|
desc->desc->base = disc_base;
|
||||||
|
desc->desc->read_only = 0; /* See above */
|
||||||
|
desc->desc->size = disc_size;
|
||||||
|
desc->slot = slot;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int asprintf(char **restrict strp, const char *restrict fmt, ...);
|
||||||
|
|
||||||
|
static disc_descr_t *disc_open_next(void *desc_in) {
|
||||||
|
unix_disc_descr_t *desc = desc_in;
|
||||||
|
if (desc->num_names == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
munmap(desc->desc->base, desc->desc->size);
|
||||||
|
desc->desc->base = 0;
|
||||||
|
desc->idx = (desc->idx + 1) % desc->num_names;
|
||||||
|
int r = open_disc_single(desc, desc->slot, desc->opt_write, desc->names[desc->idx]);
|
||||||
|
if (r == 0) return desc->desc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_disc_collection(unix_disc_descr_t *desc, int slot, int opt_write, const char *disc_filename) {
|
||||||
|
struct stat sb;
|
||||||
|
printf("Opening disc collection '%s'\n", disc_filename);
|
||||||
|
DIR *d = opendir(disc_filename);
|
||||||
|
char **names = malloc(0);
|
||||||
|
struct dirent *ent;
|
||||||
|
int cnt=0;
|
||||||
|
for(; errno=0, ent = readdir(d);) {
|
||||||
|
names = realloc(names, sizeof(const char *) * (cnt + 1));
|
||||||
|
asprintf(&names[cnt], "%s/%s", disc_filename, ent->d_name);
|
||||||
|
stat(names[cnt], &sb);
|
||||||
|
if((sb.st_mode & S_IFMT) == S_IFDIR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("Found disc %s\n", names[cnt]);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
if (errno != 0) {
|
||||||
|
perror("readdir");
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
if(cnt == 0) {
|
||||||
|
printf("Didn't find any discs\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
desc->names = names;
|
||||||
|
desc->num_names = cnt;
|
||||||
|
desc->desc->op_next = disc_open_next;
|
||||||
|
desc->desc->op_ctx = desc;
|
||||||
|
return open_disc_single(desc, slot, opt_write, names[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_disc(unix_disc_descr_t *desc, int slot, int opt_write, const char *disc_filename) {
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
int r = stat(disc_filename, &sb);
|
||||||
|
if (r < 0) {
|
||||||
|
perror("Disc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((sb.st_mode & S_IFMT) == S_IFDIR) {
|
||||||
|
if(slot == 0) {
|
||||||
|
printf("Initial disc argument must be a file, not a directory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return open_disc_collection(desc, slot, opt_write, disc_filename);
|
||||||
|
} else {
|
||||||
|
desc->desc->op_next = 0;
|
||||||
|
return open_disc_single(desc, slot, opt_write, disc_filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from micropython
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <poll.h>
|
||||||
|
static struct termios orig_termios;
|
||||||
|
|
||||||
|
static void stdio_mode_raw(void) {
|
||||||
|
// save and set terminal settings
|
||||||
|
tcgetattr(0, &orig_termios);
|
||||||
|
static struct termios termios;
|
||||||
|
termios = orig_termios;
|
||||||
|
termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||||
|
termios.c_cflag = (termios.c_cflag & ~(CSIZE | PARENB)) | CS8;
|
||||||
|
termios.c_lflag = 0;
|
||||||
|
termios.c_cc[VMIN] = 1;
|
||||||
|
termios.c_cc[VTIME] = 0;
|
||||||
|
tcsetattr(0, TCSAFLUSH, &termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stdio_mode_orig(void) {
|
||||||
|
// restore terminal settings
|
||||||
|
tcsetattr(0, TCSAFLUSH, &orig_termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pv_uart_read() {
|
||||||
|
|
||||||
|
struct pollfd p = { .fd = 0, .events = POLLIN };
|
||||||
|
int r = poll(&p, 1, 0);
|
||||||
|
if (r > 0) {
|
||||||
|
unsigned char result;
|
||||||
|
r = read(0, &result, 1);
|
||||||
|
if (r == 1) return result;
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
/* The emulator core expects to be given ROM and RAM pointers,
|
/* The emulator core expects to be given ROM and RAM pointers,
|
||||||
|
|
@ -91,11 +246,9 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *ram_base;
|
void *ram_base;
|
||||||
void *rom_base;
|
void *rom_base;
|
||||||
void *disc_base;
|
|
||||||
char *rom_filename = "rom.bin";
|
char *rom_filename = "rom.bin";
|
||||||
char *rom_dump_filename = NULL;
|
char *rom_dump_filename = NULL;
|
||||||
char *ram_filename = "ram.bin";
|
char *ram_filename = "ram.bin";
|
||||||
char *disc_filename = NULL;
|
|
||||||
int ofd;
|
int ofd;
|
||||||
int ch;
|
int ch;
|
||||||
int opt_disassemble = 0;
|
int opt_disassemble = 0;
|
||||||
|
|
@ -104,6 +257,15 @@ int main(int argc, char *argv[])
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Args
|
// Args
|
||||||
|
|
||||||
|
disc_descr_t discs[DISC_NUM_DRIVES] = {0};
|
||||||
|
unix_disc_descr_t udiscs[DISC_NUM_DRIVES] = {0};
|
||||||
|
|
||||||
|
for(int i=0; i<DISC_NUM_DRIVES; i++) {
|
||||||
|
udiscs[i].desc = &discs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t disc_num = 0;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "r:d:W:ihw")) != -1) {
|
while ((ch = getopt(argc, argv, "r:d:W:ihw")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'r':
|
case 'r':
|
||||||
|
|
@ -115,7 +277,19 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
disc_filename = strdup(optarg);
|
if (disc_num < DISC_NUM_DRIVES) {
|
||||||
|
if (open_disc(&udiscs[disc_num], disc_num, opt_write, optarg) != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
disc_num ++;
|
||||||
|
} else {
|
||||||
|
printf("Too many discs\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
opt_write = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
|
|
@ -192,40 +366,6 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
printf("RAM mapped at %p\n", (void *)ram_base);
|
printf("RAM mapped at %p\n", (void *)ram_base);
|
||||||
|
|
||||||
disc_descr_t discs[DISC_NUM_DRIVES] = {0};
|
|
||||||
|
|
||||||
if (disc_filename) {
|
|
||||||
printf("Opening disc '%s'\n", disc_filename);
|
|
||||||
// FIXME: >1 disc
|
|
||||||
ofd = open(disc_filename, opt_write ? O_RDWR : O_RDONLY);
|
|
||||||
if (ofd < 0) {
|
|
||||||
perror("Disc");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fstat(ofd, &sb);
|
|
||||||
size_t disc_size = sb.st_size;
|
|
||||||
|
|
||||||
/* Discs are always _writable_ from the perspective of
|
|
||||||
* the Mac, but by default data is a MAP_PRIVATE copy
|
|
||||||
* and is not synchronised to the backing file. If
|
|
||||||
* opt_write, we use MAP_SHARED and open the file RW,
|
|
||||||
* so writes persist to the disc image.
|
|
||||||
*/
|
|
||||||
disc_base = mmap(0, disc_size, PROT_READ | PROT_WRITE,
|
|
||||||
opt_write ? MAP_SHARED : MAP_PRIVATE,
|
|
||||||
ofd, 0);
|
|
||||||
if (disc_base == MAP_FAILED) {
|
|
||||||
printf("Can't mmap disc!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
printf("Disc mapped at %p, size %ld\n", (void *)disc_base, disc_size);
|
|
||||||
|
|
||||||
discs[0].base = disc_base;
|
|
||||||
discs[0].read_only = 0; /* See above */
|
|
||||||
discs[0].size = disc_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// SDL/UI init
|
// SDL/UI init
|
||||||
|
|
||||||
|
|
@ -243,10 +383,15 @@ int main(int argc, char *argv[])
|
||||||
perror("SDL window");
|
perror("SDL window");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const int absmouse = 1;
|
||||||
|
if (!absmouse) {
|
||||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||||
|
} else {
|
||||||
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
|
||||||
|
|
||||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
|
|
@ -269,10 +414,12 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
umac_init(ram_base, rom_base, discs);
|
umac_init(ram_base, rom_base, discs);
|
||||||
umac_opt_disassemble(opt_disassemble);
|
umac_opt_disassemble(opt_disassemble);
|
||||||
|
stdio_mode_raw();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Main loop
|
// Main loop
|
||||||
|
|
||||||
|
|
||||||
int done = 0;
|
int done = 0;
|
||||||
int mouse_button = 0;
|
int mouse_button = 0;
|
||||||
uint64_t last_vsync = 0;
|
uint64_t last_vsync = 0;
|
||||||
|
|
@ -282,7 +429,8 @@ int main(int argc, char *argv[])
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
int mousex = 0;
|
int mousex = 0;
|
||||||
int mousey = 0;
|
int mousey = 0;
|
||||||
|
int send_mouse = 0;
|
||||||
|
static int absmousex, absmousey;
|
||||||
if (SDL_PollEvent(&event)) {
|
if (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
|
|
@ -293,27 +441,37 @@ int main(int argc, char *argv[])
|
||||||
case SDL_KEYUP: {
|
case SDL_KEYUP: {
|
||||||
int c = SDLScan2MacKeyCode(event.key.keysym.scancode);
|
int c = SDLScan2MacKeyCode(event.key.keysym.scancode);
|
||||||
c = (c << 1) | 1;
|
c = (c << 1) | 1;
|
||||||
printf("Key 0x%x -> 0x%x\n", event.key.keysym.scancode, c);
|
|
||||||
if (c != MKC_None)
|
if (c != MKC_None)
|
||||||
umac_kbd_event(c, (event.type == SDL_KEYDOWN));
|
umac_kbd_event(c, (event.type == SDL_KEYDOWN));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
|
send_mouse = 1;
|
||||||
|
absmousex = event.motion.x / DISP_SCALE;
|
||||||
|
absmousey = event.motion.y / DISP_SCALE;
|
||||||
mousex = event.motion.xrel;
|
mousex = event.motion.xrel;
|
||||||
mousey = -event.motion.yrel;
|
mousey = -event.motion.yrel;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
send_mouse = 1;
|
||||||
mouse_button = 1;
|
mouse_button = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEBUTTONUP:
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
send_mouse = 1;
|
||||||
mouse_button = 0;
|
mouse_button = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (send_mouse) {
|
||||||
|
if(absmouse) {
|
||||||
|
umac_absmouse(absmousex, absmousey, mouse_button);
|
||||||
|
} else {
|
||||||
umac_mouse(mousex, mousey, mouse_button);
|
umac_mouse(mousex, mousey, mouse_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done |= umac_loop();
|
done |= umac_loop();
|
||||||
|
|
||||||
|
|
@ -339,5 +497,6 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
} while (!done);
|
} while (!done);
|
||||||
|
|
||||||
|
stdio_mode_orig();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue