- Made a lot of progress getting 3.0.0 to run.

- Implemented support for reading the kernel from SVFS/UFS filesystems
- Other little changes
This commit is contained in:
Peter Rutenbar 2014-04-05 19:20:53 -04:00
parent 0384728c22
commit e82172884e
22 changed files with 1682 additions and 536 deletions

View File

@ -1,12 +1,13 @@
CC = clang
CFLAGS = -O4 -arch x86_64 -Wno-deprecated-declarations
CFLAGS = -O3 -arch i386 -arch x86_64 -Wno-deprecated-declarations
LFLAGS = -framework OpenGL -framework GLUT
all: shoebill
shoebill: make_core test.c
$(CC) $(LFLAGS) $(CFLAGS) -L intermediates -l shoebill_core test.c -o shoebill
shoebill: make_core
# shoebill: make_core test.c
# $(CC) $(LFLAGS) $(CFLAGS) -L intermediates -l shoebill_core test.c -o shoebill
make_core:
$(MAKE) -C core -j 4

View File

@ -1,20 +1,34 @@
CC = clang
CFLAGS = -O4 -ggdb -arch x86_64 -Wno-deprecated-declarations
CFLAGS = -O3 -flto -ggdb -Wno-deprecated-declarations
DEPS = core_api.h coff.h mc68851.h redblack.h shoebill.h Makefile macro.pl
NEED_DECODER = cpu dis
NEED_PREPROCESSING = adb fpu mc68851 mem via
NEED_NOTHING = atrap_tab coff exception floppy macii_symbols redblack scsi toby_frame_buffer video core_api
NEED_NOTHING = atrap_tab coff exception floppy macii_symbols redblack scsi toby_frame_buffer video core_api filesystem debug_server
# Object files that can be compiled directly from the source
OBJ_NEED_NOTHING = $(patsubst %,$(TEMP)/%.o,$(NEED_NOTHING))
# Object files than need preprocessing with macro.pl
OBJ_NEED_PREPROCESSING = $(patsubst %,$(TEMP)/%.o,$(NEED_PREPROCESSING))
# Object files that depend on the instruction decoder
OBJ_NEED_DECODER = $(patsubst %,$(TEMP)/%.o,$(NEED_DECODER))
# Files that NEED_DECODER also NEED_PREPROCESSING
POST_PREPROCESSING = $(patsubst %,$(TEMP)/%.post.c,$(NEED_PREPROCESSING)) $(patsubst %,$(TEMP)/%.post.c,$(NEED_DECODER))
# All the object files compiled for x86_64
OBJ_x86_64 = $(OBJ_NEED_NOTHING) $(OBJ_NEED_PREPROCESSING) $(OBJ_NEED_DECODER)
# The object files compiled for i386 (the same as x86_64 files, but with .i386 appended)
OBJ_i386 = $(patsubst %,%.i386,$(OBJ_x86_64))
MACRO = perl macro.pl
TEMP = ../intermediates
@ -22,18 +36,29 @@ TEMP = ../intermediates
all: $(TEMP)/libshoebill_core.a
$(TEMP)/libshoebill_core.a: $(TEMP) $(DEPS) $(OBJ_NEED_NOTHING) $(OBJ_NEED_PREPROCESSING) $(OBJ_NEED_DECODER)
libtool -static -o $(TEMP)/libshoebill_core.a $(OBJ_NEED_NOTHING) $(OBJ_NEED_PREPROCESSING) $(OBJ_NEED_DECODER)
$(TEMP)/libshoebill_core.a: $(TEMP) $(DEPS) $(OBJ_x86_64)
libtool -static -v -o $(TEMP)/libshoebill_core.a.x86_64 $(OBJ_x86_64)
libtool -static -v -o $(TEMP)/libshoebill_core.a.i386 $(OBJ_i386)
lipo -create -output $(TEMP)/libshoebill_core.a $(TEMP)/libshoebill_core.a.x86_64 $(TEMP)/libshoebill_core.a.i386
# Split object files into i386/x86_64 versions, since it seems that libtool is unable to
# link a static universal library for -O4 object files.
# x86_64 object files have the form "intermediates/<file_name>.o
# i386 object files have the form "intermediates/<file_name>.o.i386
# Build object files
$(OBJ_NEED_NOTHING): $(TEMP)/%.o: %.c $(DEPS)
$(CC) -c $(CFLAGS) $< -o $@
$(CC) -c -arch x86_64 $(CFLAGS) $< -o $@
$(CC) -c -arch i386 $(CFLAGS) $< -o $@.i386
$(OBJ_NEED_PREPROCESSING): $(TEMP)/%.o: $(TEMP)/%.post.c $(DEPS)
$(CC) -c $(CFLAGS) $< -o $@
$(CC) -c -arch x86_64 $(CFLAGS) $< -o $@
$(CC) -c -arch i386 $(CFLAGS) $< -o $@.i386
$(OBJ_NEED_DECODER): $(TEMP)/%.o: $(TEMP)/%.post.c $(DEPS) $(TEMP)/dis_decoder_guts.c $(TEMP)/inst_decoder_guts.c
$(CC) -c $(CFLAGS) $< -o $@
$(CC) -c -arch x86_64 $(CFLAGS) $< -o $@
$(CC) -c -arch i386 $(CFLAGS) $< -o $@.i386
# Preprocess C files
$(POST_PREPROCESSING): $(TEMP)/%.post.c: %.c $(DEPS)

View File

@ -148,11 +148,22 @@ static void mouse_talk(uint8_t reg)
case 0:
if (shoe.mouse.changed) {
const int32_t hi_delta_limit = 32;
const int32_t low_delta_limit = -32;
printf("mouse_talk: x=%d, y=%d button=%u\n", shoe.mouse.delta_x, shoe.mouse.delta_y, shoe.mouse.button_down);
int32_t x = shoe.mouse.delta_x;
int32_t y = shoe.mouse.delta_y;
shoe.adb.data[1] = shoe.mouse.delta_x & 0x7f;
shoe.adb.data[0] = shoe.mouse.delta_y & 0x7f;
//printf("mouse_talk: x=%d, y=%d button=%u\n", shoe.mouse.delta_x, shoe.mouse.delta_y, shoe.mouse.button_down);
if (x > hi_delta_limit) x = hi_delta_limit;
if (x < low_delta_limit) x = low_delta_limit;
if (y > hi_delta_limit) y = hi_delta_limit;
if (y < low_delta_limit) y = low_delta_limit;
shoe.adb.data[1] = x & 0x7f;
shoe.adb.data[0] = y & 0x7f;
if (!shoe.mouse.button_down) {
//shoe.adb.data[1] |= 0x80;
shoe.adb.data[0] |= 0x80;
@ -164,7 +175,7 @@ static void mouse_talk(uint8_t reg)
shoe.mouse.delta_x = 0;
shoe.mouse.delta_y = 0;
// shoe.mouse.button_down = 0;
shoe.mouse.changed = 0;
}
else

View File

@ -144,9 +144,11 @@ void shoebill_start()
pthread_mutex_unlock(&shoe.cpu_thread_lock);
pthread_mutex_unlock(&shoe.via_clock_thread_lock);
}
static void _cpu_loop_fast()
{
void *_cpu_thread (void *arg) {
pthread_mutex_lock(&shoe.cpu_thread_lock);
while (1) {
if (shoe.cpu_thread_notifications) {
@ -159,16 +161,13 @@ static void _cpu_loop_fast()
if (shoe.cpu_thread_notifications & SHOEBILL_STATE_STOPPED) {
continue; // FIXME: yield or block on a condition variable here
}
if (shoe.cpu_thread_notifications & SHOEBILL_STATE_SWITCH_MODE)
return ;
}
cpu_step();
}
}
static void _cpu_loop_debug()
/*static void _cpu_loop_debug()
{
while (1) {
if (shoe.cpu_thread_notifications) {
@ -181,33 +180,9 @@ static void _cpu_loop_debug()
}
}
}
}*/
void *_cpu_thread (void *arg) {
pthread_mutex_lock(&shoe.cpu_thread_lock);
while (1) {
shoe.cpu_thread_notifications &= ~SHOEBILL_STATE_SWITCH_MODE;
if (shoe.cpu_mode == CPU_MODE_FAST)
_cpu_loop_fast();
else if (shoe.cpu_mode == CPU_MODE_DEBUG)
_cpu_loop_debug();
else if (shoe.cpu_mode == CPU_MODE_STEPI) {
cpu_step();
shoe.cpu_mode = CPU_MODE_STEPI_COMPLETE;
while (shoe.cpu_mode == CPU_MODE_STEPI_COMPLETE)
pthread_yield_np();
}
else if (shoe.cpu_mode == CPU_MODE_FREEZE) {
pthread_mutex_lock(&shoe.cpu_freeze_lock);
pthread_mutex_unlock(&shoe.cpu_freeze_lock);
}
}
}
void shoebill_cpu_stepi (void)
/*void shoebill_cpu_stepi (void)
{
if (shoe.cpu_mode != CPU_MODE_FREEZE)
return ;
@ -231,7 +206,7 @@ void shoebill_cpu_freeze (void)
while (shoe.cpu_thread_notifications & SHOEBILL_STATE_SWITCH_MODE);
pthread_yield_np();
}
}*/
/*
* The A/UX bootloader blasts this structure into memory
@ -338,7 +313,7 @@ static void _init_macintosh_lomem_globals (const uint32_t offset)
#define hwCbADB (1<<10)
#define hwCbAUX (1<<9) /* not sure if I need to set this one */
const uint16_t HWCfgFlags = hwCbSCSI | hwCbClock | hwCbFPU | hwCbMMU | hwCbADB;
pset(0xb22, 2, HWCfgFlags); // HWCfgFlags
pset(offset+0xb22, 2, HWCfgFlags); // HWCfgFlags
}
@ -587,40 +562,6 @@ fail:
return 0;
}
/*static uint32_t _setup_nubus_cards(shoebill_control_t *control)
{
uint32_t i;
for (i=0; i<16; i++) {
switch (control->slots[i].card_type) {
case card_empty:
continue;
case card_toby_frame_buffer:
case card_shoebill_ethernet:
assert(!"not implemented");
case card_shoebill_video: {
const uint16_t width = control->slots[i].card.video.width;
const uint16_t height = control->slots[i].card.video.height;
const uint16_t scanline_width = control->slots[i].card.video.scanline_width;
const double refresh_rate = control->slots[i].card.video.refresh_rate;
uint8_t *frame_buffer = control->slots[i].card.video.frame_buffer;
assert(scanline_width >= width);
nubus_video_init(i, width, height, scanline_width, refresh_rate, frame_buffer);
}
}
}
return 1;
fail:
return 0;
}*/
static uint32_t _load_aux_kernel(shoebill_control_t *control, coff_file *coff, uint32_t *_pc)
{
uint32_t j, i, pc = 0xffffffff;
@ -801,7 +742,8 @@ uint32_t shoebill_initialize(shoebill_control_t *control)
pthread_mutex_lock(&shoe.via_clock_thread_lock);
pthread_create(&control->cpu_thread_pid, NULL, _cpu_thread, NULL);
pthread_create(&control->cpu_thread_pid, NULL, via_clock_thread, NULL);
// pthread_create(&control->cpu_thread_pid, NULL, debug_cpu_thread, NULL);
pthread_create(&control->via_thread_pid, NULL, via_clock_thread, NULL);
return 1;
@ -885,6 +827,7 @@ void shoebill_mouse_move(int32_t x, int32_t y)
void shoebill_mouse_move_delta (int32_t x, int32_t y)
{
assert(pthread_mutex_lock(&shoe.adb.lock) == 0);
shoe.mouse.delta_x += x;
shoe.mouse.delta_y += y;

View File

@ -95,7 +95,7 @@ typedef struct {
} card;
} slots[16];
pthread_t cpu_thread_pid, clock_pid;
pthread_t cpu_thread_pid, via_thread_pid;
char error_msg[8192];
} shoebill_control_t;
@ -126,4 +126,6 @@ void shoebill_mouse_click(uint8_t down);
void shoebill_start();
uint8_t* shoebill_extract_kernel(const char *disk_path, const char *kernel_path, char *error_str, uint32_t *len);
#endif

View File

@ -31,7 +31,7 @@
#include "../core/mc68851.h"
global_shoebill_context_t shoe;
struct dbg_state_t dbg_state;
//struct dbg_state_t dbg_state;
#define nextword() ({const uint16_t w=lget(shoe.pc,2); if (shoe.abort) {return;}; shoe.pc+=2; w;})
#define verify_supervisor() {if (!sr_s()) {throw_privilege_violation(); return;}}
@ -867,7 +867,7 @@ struct dbg_state_t dbg_state;
const uint8_t Rm = mib(R, 4);
const uint8_t Sm = mib(shoe.dat, 4);
const uint8_t Dm = mib(shoe.a[r], 4);
set_sr_z(chop(R,sz)==0);
set_sr_z(R == 0); /* <- This is where A/UX 3.0.0 started working */
set_sr_n(Rm);
set_sr_v((!Sm && Dm && !Rm) || (Sm && !Dm && Rm));
set_sr_c((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm));
@ -1162,7 +1162,8 @@ struct dbg_state_t dbg_state;
// 1: reset the "enabled" bit of the TC register
printf("Reset! (not implemented)\n");
dbg_state.running = 0;
assert(!"reset called");
//dbg_state.running = 0;
})
~inst(movec, {
@ -1359,11 +1360,13 @@ struct dbg_state_t dbg_state;
shoe.dat = R;
call_ea_write(M, sz);
set_sr_z(R == 0);
set_sr_n(Rm);
const uint32_t result = chop(R, sz);
set_sr_z(result == 0);
set_sr_c(result != 0);
set_sr_x(result != 0);
set_sr_v(Dm && Rm);
set_sr_c(Dm || Rm);
set_sr_x(Dm || Rm);
set_sr_n(Rm);
})
~inst(negx, {

126
core/debug_server.c Normal file
View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2014, Peter Rutenbar <pruten@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "../core/shoebill.h"
#include "../core/coff.h"
#define DEBUG_MODE_STOPPED 0
#define DEBUG_MODE_RUNNING 1
#define DEBUG_MODE_STEP 2
#define SHOEBILL_DEBUG_PORT 0xfded
static int _start_debug_server(void)
{
struct sockaddr_in addr;
int sock = socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(struct sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(SHOEBILL_DEBUG_PORT);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (sock == -1) {
assert(!"can't socket");
}
else if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) != 0) {
assert(!"can't bind");
// return -1;
}
else if (listen(sock, 1) != 0) {
assert(!"can't listen");
}
return sock;
}
void *debug_server_thread (void *arg)
{
struct sockaddr_in addr;
socklen_t sin_size = sizeof(struct sockaddr_in);
uint8_t *inbuf = calloc(0x10000, 1);
uint8_t *outbuf = calloc(0x10000, 1);
int sock = _start_debug_server();
int clientfd = accept(sock, (struct sockaddr*)&addr, &sin_size);
shoe.dbg.connected = 1;
shoe.dbg.mode = DEBUG_MODE_RUNNING;
return NULL;
}
void *debug_cpu_thread (void *arg)
{
memset(&shoe.dbg, 0, sizeof(shoe.dbg));
shoe.dbg.mode = DEBUG_MODE_STOPPED;
pthread_t server_thread_pid;
pthread_create(&server_thread_pid,
NULL,
debug_server_thread,
NULL);
/*
* The CPU only runs once the debugger is connected, and the
* emulator has started
*/
pthread_mutex_lock(&shoe.cpu_thread_lock);
while (!shoe.dbg.connected)
usleep(1000);
while (1) {
if (shoe.dbg.mode == DEBUG_MODE_RUNNING) {
if (!shoe.dbg.ignore_interrupts &&
(shoe.cpu_thread_notifications & 0xff)) {
process_pending_interrupt();
}
if (shoe.cpu_thread_notifications & SHOEBILL_STATE_STOPPED) {
continue;
}
cpu_step();
}
else if (shoe.dbg.mode == DEBUG_MODE_STOPPED)
pthread_yield_np();
else if (shoe.dbg.mode == DEBUG_MODE_STEP) {
cpu_step();
shoe.dbg.mode = DEBUG_MODE_STOPPED;
}
}
}

View File

@ -215,9 +215,9 @@ void throw_illegal_instruction()
{
//printf("throw_illegal_instruction(): I'm throwing an illegal instruction exception! (shoe.pc = 0x%08x, op=0x%04x, a7=0x%08x)\n", shoe.orig_pc, shoe.op, shoe.a[7]);
if ((shoe.op != 0xf010) && ((shoe.op >> 12) != 0xa))
/*if ((shoe.op != 0xf010) && ((shoe.op >> 12) != 0xa))
//assert(!"illegal");
dbg_state.running = 0;
dbg_state.running = 0; */
// fetch vector number
const uint32_t vector_num =

1389
core/filesystem.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -258,7 +258,8 @@ void inst_fpu_decode ()
}
printf("inst_fpu_decode: unhandled instruction: %s op=0x%04x ext = 0x%04x pc=0x%08x\n", fpu_inst_table[name].name, shoe.op, ext, shoe.orig_pc);
dbg_state.running = 0;
assert(!"unknown fpu inst");
//dbg_state.running = 0;
}

View File

@ -365,6 +365,9 @@ void _logical_get (void)
void logical_set (void)
{
if ((shoe.logical_addr >= 0xaf2) && (shoe.logical_addr < 0xaf6) && (shoe.logical_size == 1) && ((shoe.logical_dat&0xff) == 0xff)) {
shoe.logical_dat = 0;
}
// if ((shoe.logical_addr >= 0x12fffff6) && (shoe.logical_addr <= 0x12ffffff))
// printf("aux3: setting 0x%08x = 0x%x\n", shoe.logical_addr, (uint32_t)shoe.logical_dat);
//

View File

@ -26,10 +26,12 @@
#ifndef _SHOEBILL_H
#define _SHOEBILL_H
#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <sys/time.h>
#include <histedit.h>
#include <pthread.h>
//#include <histedit.h>
#include "coff.h"
@ -138,13 +140,14 @@ typedef struct dbg_breakpoint_t {
uint64_t num;
} dbg_breakpoint_t;
struct dbg_state_t {
EditLine *el;
uint8_t running;
typedef struct {
// EditLine *el;
uint8_t mode;
uint8_t ignore_interrupts;
uint8_t connected;
uint64_t breakpoint_counter;
dbg_breakpoint_t *breakpoints;
};
extern struct dbg_state_t dbg_state;
} debugger_state_t;
typedef enum {
adb_talk,
@ -257,7 +260,6 @@ typedef struct {
typedef struct {
#define SHOEBILL_STATE_STOPPED (1<<9)
#define SHOEBILL_STATE_SWITCH_MODE (1<<10)
// bits 0-6 are CPU interrupt priorities
// bit 8 indicates that STOP was called
@ -267,13 +269,6 @@ typedef struct {
pthread_mutex_t via_clock_thread_lock;
pthread_mutex_t cpu_freeze_lock;
#define CPU_MODE_FAST 0
#define CPU_MODE_DEBUG 1
#define CPU_MODE_STEPI 2
#define CPU_MODE_STEPI_COMPLETE 3
#define CPU_MODE_FREEZE 4
uint32_t cpu_mode;
// -- PMMU caching structures ---
struct {
pmmu_cache_entry_t entry[512];
@ -427,7 +422,6 @@ typedef struct {
via_clock_t via_clocks;
uint32_t dbg;
struct timeval start_time; // when the emulator started (for computing timer interrupts)
uint64_t total_ticks; // how many 60hz ticks have been generated
@ -437,6 +431,8 @@ typedef struct {
coff_file *launch; // FIXME: delete me: coff symbols from aux 1.1.1 launch binary
scsi_device_t scsi_devices[8]; // SCSI devices
debugger_state_t dbg;
} global_shoebill_context_t;
extern global_shoebill_context_t shoe; // declared in cpu.c
@ -448,7 +444,7 @@ void fpu_setup_jump_table();
// cpu.c fuctions
void cpu_step (void);
inline void inst_decode (void);
void inst_decode (void);
// exception.c functions
@ -463,10 +459,10 @@ void throw_frame_two (uint16_t sr, uint32_t next_pc, uint32_t vector_num, uint32
// mem.c functions
void inline physical_get (void);
void physical_get (void);
#define pget(addr, s) ({shoe.physical_addr=(addr); shoe.physical_size=(s); physical_get(); shoe.physical_dat;})
void inline logical_get (void);
void logical_get (void);
#define lget_fc(addr, s, fc) ({ \
shoe.logical_addr=(addr); \
shoe.logical_size=(s); \
@ -483,10 +479,10 @@ void inline logical_get (void);
shoe.logical_dat; \
})
void inline physical_set (void);
void physical_set (void);
#define pset(addr, s, val) {shoe.physical_addr=(addr); shoe.physical_size=(s); shoe.physical_dat=(val); physical_set();}
void inline logical_set (void);
void logical_set (void);
#define lset_fc(addr, s, val, fc) {\
shoe.logical_addr=(addr); \
shoe.logical_size=(s); \
@ -536,7 +532,7 @@ void ea_addr();
void disassemble_inst(uint8_t binary[24], uint32_t orig_pc, char *str, uint32_t *instlen);
char* decode_ea_rw (uint8_t mr, uint8_t sz);
char* decode_ea_addr (uint8_t mr);
inline void dis_decode(void);
void dis_decode(void);
uint16_t dis_next_word (void);
char* decode_ea_addr (uint8_t mr);
char* decode_ea_rw (uint8_t mr, uint8_t sz);
@ -630,5 +626,9 @@ uint32_t nubus_video_read_func(const uint32_t rawaddr, const uint32_t size,
void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
const uint32_t data, const uint8_t slotnum);
// debug_server.c
void *debug_cpu_thread (void *arg);
#endif // _SHOEBILL_H

View File

@ -414,6 +414,7 @@ void *via_clock_thread(void *arg)
}
// Check if any nubus cards have interrupt timers
shoe.via[1].rega = 0b00111111;
for (i=9; i<15; i++) {
if (!shoe.slots[i].connected)
continue;
@ -424,7 +425,8 @@ void *via_clock_thread(void *arg)
fire(1.0L/shoe.slots[i].interrupt_rate);
if (shoe.slots[i].interrupts_enabled) {
shoe.via[1].rega = 0b00111111 & ~~(1<<(i-9));
// shoe.via[1].rega = 0b00111111 & ~~(1<<(i-9));
shoe.via[1].rega &= 0b00111111 & ~~(1<<(i-9));
via_raise_interrupt(2, IFR_CA1);
printf("Fired nubus interrupt %u\n", i);
}

View File

@ -256,9 +256,10 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@ -284,8 +285,9 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.8;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
ONLY_ACTIVE_ARCH = NO;
SDKROOT = macosx10.8;
VALID_ARCHS = "x86_64 i386";
};
name = Debug;
};
@ -293,9 +295,10 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@ -316,15 +319,19 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.8;
SDKROOT = macosx;
SDKROOT = macosx10.8;
VALID_ARCHS = "x86_64 i386";
};
name = Release;
};
87F9775A18987700000D589E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = NO;
COMBINE_HIDPI_IMAGES = YES;
GCC_FAST_OBJC_DISPATCH = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Shoebill/Shoebill-Prefix.pch";
INFOPLIST_FILE = "Shoebill/Shoebill-Info.plist";
@ -332,7 +339,9 @@
"$(inherited)",
../intermediates,
);
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx10.8;
WRAPPER_EXTENSION = app;
};
name = Debug;
@ -340,8 +349,11 @@
87F9775B18987700000D589E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_OBJC_ARC = NO;
COMBINE_HIDPI_IMAGES = YES;
GCC_FAST_OBJC_DISPATCH = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Shoebill/Shoebill-Prefix.pch";
INFOPLIST_FILE = "Shoebill/Shoebill-Info.plist";
@ -350,6 +362,7 @@
../intermediates,
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx10.8;
WRAPPER_EXTENSION = app;
};
name = Release;

View File

@ -16,10 +16,12 @@
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>0.0.1</string>
<key>CFBundleShortVersionString</key>
<string>0.0.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.0.2</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSMainNibFile</key>

View File

@ -307,7 +307,12 @@
return ;
}
[self createScreenWindow:10 height:height width:width refresh_freq:200.0/3.0];
[self createScreenWindow:9 height:height width:width refresh_freq:200.0/3.0];
/*[self createScreenWindow:10 height:height width:width refresh_freq:200.0/3.0];
[self createScreenWindow:11 height:height width:width refresh_freq:200.0/3.0];
[self createScreenWindow:12 height:height width:width refresh_freq:200.0/3.0];
[self createScreenWindow:13 height:height width:width refresh_freq:200.0/3.0];
[self createScreenWindow:14 height:height width:width refresh_freq:200.0/3.0];*/
shoebill_start();
isRunning = true;

View File

@ -105,7 +105,7 @@
if ([urls count] != 1)
return ;
NSURL *url = [urls firstObject];
NSURL *url = [urls objectAtIndex:0];
if (![url isFileURL])
return ;

View File

@ -73,11 +73,17 @@
colorspace = CGColorSpaceCreateDeviceRGB();
timer = [NSTimer
scheduledTimerWithTimeInterval:(0.015/2.0)
scheduledTimerWithTimeInterval:0.001
target:self
selector:@selector(timerFireMethod:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer
forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer:timer
forMode:NSEventTrackingRunLoopMode];
shoebill_card_video_t *video = &control->slots[10].card.video;
NSSize size = {
@ -106,7 +112,8 @@
maxX = NSMaxX(bounds);
maxY = NSMaxY(bounds);
//[self update];
GLint swapInt = 1;
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
if(NSIsEmptyRect([self visibleRect]))
{
@ -180,7 +187,16 @@ static void _do_clut_translation(shoebill_card_video_t *ctx)
glClearColor(0.0, 0.0, 0.0, 0.0);
if (shoeApp->isRunning) {
shoebill_card_video_t *video = &control->slots[10].card.video;
uint8_t slotnum = ((shoeScreenWindow*)[self window])->slotnum;
shoebill_card_video_t *video = &control->slots[slotnum].card.video;
/*NSSize size = {
.height=video->height,
.width=video->width
};
[self setFrameSize:size];
[[self window] setContentSize:size];*/
_do_clut_translation(video);
glViewport(0, 0, video->width, video->height);
glRasterPos2i(0, video->height);

View File

@ -32,6 +32,16 @@
- (void)configure:(uint8_t) _slotnum
{
slotnum = _slotnum;
shoeApplication *shoeApp = (shoeApplication*) NSApp;
shoebill_control_t *control = &shoeApp->control;
shoebill_card_video_t *video = &control->slots[slotnum].card.video;
NSSize size = {
.height=video->height,
.width=video->width
};
[self setContentSize:size];
}
// Called after all the shoeScreenWindows are created and configured,
@ -107,4 +117,5 @@
[self setTitle:@"Shoebill - Screen 1 (Ctrl-click to escape)"];
}
@end

407
test.c
View File

@ -1,407 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <GLUT/glut.h>
#include "core/shoebill.h"
#include "core/core_api.h"
shoebill_control_t control;
shoebill_card_video_t *video_card = NULL;
void glut_display_func (void)
{
uint32_t myw = glutGet(GLUT_WINDOW_WIDTH);
uint32_t myh = glutGet(GLUT_WINDOW_HEIGHT);
uint32_t slotnum, i;
shoebill_card_video_t *ctx = video_card;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, myw, 0, myh, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.1, 0.1, 0.8);
uint32_t gli = 0;
switch (ctx->depth) {
case 1: {
for (i=0; i < ctx->pixels/8; i++) {
const uint8_t byte = ctx->indexed_buf[i];
ctx->direct_buf[i * 8 + 0] = ctx->clut[(byte >> 7) & 1];
ctx->direct_buf[i * 8 + 1] = ctx->clut[(byte >> 6) & 1];
ctx->direct_buf[i * 8 + 2] = ctx->clut[(byte >> 5) & 1];
ctx->direct_buf[i * 8 + 3] = ctx->clut[(byte >> 4) & 1];
ctx->direct_buf[i * 8 + 4] = ctx->clut[(byte >> 3) & 1];
ctx->direct_buf[i * 8 + 5] = ctx->clut[(byte >> 2) & 1];
ctx->direct_buf[i * 8 + 6] = ctx->clut[(byte >> 1) & 1];
ctx->direct_buf[i * 8 + 7] = ctx->clut[(byte >> 0) & 1];
}
break;
}
case 2: {
for (i=0; i < ctx->pixels/4; i++) {
const uint8_t byte = ctx->indexed_buf[i];
ctx->direct_buf[i * 4 + 0] = ctx->clut[(byte >> 6) & 3];
ctx->direct_buf[i * 4 + 1] = ctx->clut[(byte >> 4) & 3];
ctx->direct_buf[i * 4 + 2] = ctx->clut[(byte >> 2) & 3];
ctx->direct_buf[i * 4 + 3] = ctx->clut[(byte >> 0) & 3];
}
break;
}
case 4: {
for (i=0; i < ctx->pixels/2; i++) {
const uint8_t byte = ctx->indexed_buf[i];
ctx->direct_buf[i * 2 + 0] = ctx->clut[(byte >> 4) & 0xf];
ctx->direct_buf[i * 2 + 1] = ctx->clut[(byte >> 0) & 0xf];
}
break;
}
case 8:
for (i=0; i < ctx->pixels; i++)
ctx->direct_buf[i] = ctx->clut[ctx->indexed_buf[i]];
break;
default:
assert(!"unknown depth");
}
glViewport(0, 0, myw, myh);
glRasterPos2i(0, myh);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelZoom(1.0, -1.0);
glDrawPixels(myw, myh, GL_RGBA, GL_UNSIGNED_BYTE, ctx->direct_buf);
glFlush();
}
/*void vbl_callback (shoebill_control_t *ctrl, uint8_t slotnum)
{
}
void video_depth_calback (sheobill_control_t *ctrl, uint8_t slotnum)
{
}*/
#define KEY_SHIFT 1
const struct {
uint8_t code;
char c;
uint8_t modifiers;
} key_codes[] = {
{0x0, 'A', 0},
{0x1, 'S', 0},
{2, 'D', 0},
{3, 'F', 0},
{4, 'H', 0},
{5, 'G', 0},
{6, 'Z', 0},
{7, 'X', 0},
{8, 'C', 0},
{9, 'V', 0},
// {0xa ??
{0xb, 'B', 0},
{0xc, 'Q', 0},
{0xd, 'W', 0},
{0xe, 'E', 0},
{0xf, 'R', 0},
{0x10, 'Y', 0},
{0x11, 'T', 0},
{0x12, '1', 0},
{0x12, '!', KEY_SHIFT},
{0x13, '2', 0},
{0x13, '@', KEY_SHIFT},
{0x14, '3', 0},
{0x14, '#', KEY_SHIFT},
{0x15, '4', 0},
{0x15, '$', KEY_SHIFT},
{0x16, '6', 0},
{0x16, '^', KEY_SHIFT},
{0x17, '5', 0},
{0x17, '%', KEY_SHIFT},
{0x18, '=', 0},
{0x18, '+', KEY_SHIFT},
{0x19, '9', 0},
{0x19, '(', KEY_SHIFT},
{0x1a, '7', 0},
{0x1a, '&', KEY_SHIFT},
{0x1b, '-', 0},
{0x1b, '_', KEY_SHIFT},
{0x1c, '8', 0},
{0x1c, '*', KEY_SHIFT},
{0x1d, '0', 0},
{0x1d, ')', KEY_SHIFT},
{0x1e, ']', 0},
{0x1e, '}', KEY_SHIFT},
{0x1f, 'O', 0},
{0x20, 'U', 0},
{0x21, '[', 0},
{0x21, '{', KEY_SHIFT},
{0x22, 'I', 0},
{0x23, 'P', 0},
{0x24, '\n', 0},
{0x24, '\r', 0},
{0x25, 'L', 0},
{0x26, 'J', 0},
{0x27, '"', KEY_SHIFT},
{0x27, '\'', 0},
{0x28, 'K', 0},
{0x29, ';', 0},
{0x29, ':', KEY_SHIFT},
{0x2a, '\\', 0},
{0x2a, '|', KEY_SHIFT},
{0x2b, ',', 0},
{0x2b, '<', KEY_SHIFT},
{0x2c, '/', 0},
{0x2c, '?', 0},
{0x2d, 'N', 0},
{0x2e, 'M', 0},
{0x2f, '.', 0},
{0x2f, '>', KEY_SHIFT},
{0x30, '\t', 0},
{0x31, ' ', 0},
{0x32, '`', 0},
{0x32, '~', KEY_SHIFT},
{0x33, '\b', 0},
{0x33, 0x7f, 0},
// {0x34, ??
// {0x35 // escape char
// 0x36 // ctrl
// 0x37 // command
// 0x38 // shift
// 0x39 // caps lock
// 0x3a // option
// 0x3b // left arrow
// 0x3c // right arrow
// 0x3d // down arrow
// 0x3e // up arrow
{0, 0, 0},
};
static uint8_t lookup_key(char c)
{
uint32_t i;
uint8_t upper=toupper(c);
for (i=0; key_codes[i].c; i++) {
if (key_codes[i].c == upper)
return key_codes[i].code;
}
return 0xff;
}
static uint8_t lookup_special(int special)
{
switch (special) {
case GLUT_KEY_UP: return 0x3e;
case GLUT_KEY_DOWN: return 0x3d;
case GLUT_KEY_LEFT: return 0x3b;
case GLUT_KEY_RIGHT: return 0x3c;
default: return 0xff;
}
}
static void keyboard_add_entry(uint8_t code, uint8_t up)
{
uint8_t up_mask = up ? 0x80 : 0;
uint32_t i;
int modifiers = glutGetModifiers();
assert(pthread_mutex_lock(&shoe.adb.lock) == 0);
if ((shoe.key.key_i+1) < KEYBOARD_STATE_MAX_KEYS) {
if (modifiers & GLUT_ACTIVE_SHIFT) {
shoe.key.keys[shoe.key.key_i].code_a = 0x38;
shoe.key.keys[shoe.key.key_i].code_b = 0xff;
shoe.key.key_i++;
}
else if (shoe.key.down_modifiers & GLUT_ACTIVE_SHIFT) {
shoe.key.keys[shoe.key.key_i].code_a = 0x80 | 0x38;
shoe.key.keys[shoe.key.key_i].code_b = 0xff;
shoe.key.key_i++;
}
shoe.key.keys[shoe.key.key_i].code_a = code | up_mask;
shoe.key.keys[shoe.key.key_i].code_b = 0xff;
shoe.key.key_i++;
}
shoe.key.down_modifiers = modifiers;
adb_request_service_request(2);
pthread_mutex_unlock(&shoe.adb.lock);
}
void global_mouse_func (int button, int state, int x, int y)
{
//if (button != GLUT_LEFT_BUTTON)
// return ;
assert(pthread_mutex_lock(&shoe.adb.lock) == 0);
shoe.mouse.button_down = (state == GLUT_DOWN);
shoe.mouse.changed = 1;
adb_request_service_request(3);
pthread_mutex_unlock(&shoe.adb.lock);
// printf("mouse_func: setting service request\n");
}
static void move_mouse (int x, int y, uint8_t button_down)
{
printf("%s: lock\n", __func__); fflush(stdout);
assert(pthread_mutex_lock(&shoe.adb.lock) == 0);
int32_t delta_x = x - shoe.mouse.old_x;
int32_t delta_y = y - shoe.mouse.old_y;
shoe.mouse.old_x = x;
shoe.mouse.old_y = y;
shoe.mouse.delta_x += delta_x;
shoe.mouse.delta_y += delta_y;
shoe.mouse.button_down = button_down;
shoe.mouse.changed = 1;
adb_request_service_request(3);
printf("%s: unlock\n", __func__); fflush(stdout);
pthread_mutex_unlock(&shoe.adb.lock);
// printf("move_mouse: setting service request\n");
}
void global_motion_func (int x, int y)
{
move_mouse(x, y, 1);
}
void global_passive_motion_func (int x, int y)
{
move_mouse(x, y, 0);
}
void global_keyboard_up_func (unsigned char c, int x, int y)
{
uint8_t code = lookup_key(c);
if (code != 0xff)
keyboard_add_entry(code, 1);
}
void global_keyboard_down_func (unsigned char c, int x, int y)
{
uint8_t code = lookup_key(c);
if (code != 0xff)
keyboard_add_entry(code, 0);
}
void global_special_up_func (int special, int x, int y)
{
const uint8_t code = lookup_special(special);
if (code != 0xff)
keyboard_add_entry(code, 1);
}
void global_special_down_func (int special, int x, int y)
{
const uint8_t code = lookup_special(special);
if (code != 0xff)
keyboard_add_entry(code, 0);
}
void timer_func (int arg)
{
glutTimerFunc(15, timer_func, 0); // 66.67hz is the usual refresh interval (right?)
glutPostRedisplay();
}
int main (int argc, char **argv)
{
bzero(&control, sizeof(shoebill_control_t));
control.aux_verbose = 1;
control.ram_size = 1024*1024*1024;
control.aux_kernel_path = "priv/unix2";
control.rom_path = "priv/macii.rom";
control.scsi_devices[0].path = "priv/aux2.img";
uint32_t result = shoebill_initialize(&control);
if (!result) {
printf("fail: %s\n", control.error_msg);
return 0;
}
else
printf("success!\n");
shoebill_install_video_card(&control, 10, 800, 600,
(2.0/3.0) * 100.0); // 66.67hz
video_card = &control.slots[10].card.video;
int dummyargc = 1;
glutInit(&dummyargc, argv);
glutInitWindowSize(video_card->scanline_width, video_card->height);
glutCreateWindow("");
glutDisplayFunc(glut_display_func);
glShadeModel(GL_FLAT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0.1, 1.0, 0.1, 1.0);
shoebill_start();
glutTimerFunc(15, timer_func, 0);
glutMainLoop();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB