Resuscitated the toby frame buffer

- Integrated it into the SDL GUI (via the "toby" cli parameter)
- It does not include the card ROM, so it will not run on A/UX 1, 2, or 3
This commit is contained in:
Peter Rutenbar 2014-06-15 16:41:06 -04:00
parent 42fd2a0b4e
commit f051d42597
12 changed files with 255 additions and 235 deletions

View File

@ -4,7 +4,7 @@ A Macintosh II emulator that runs A/UX (and A/UX only).
Shoebill is an all-new, BSD-licensed Macintosh II emulator designed from the ground up with the singular goal of running A/UX.
Shoebill requires a OS X, a Macintosh II, IIx or IIcx ROM, and a disk image with A/UX installed.
Shoebill requires OS X, a Macintosh II, IIx or IIcx ROM, and a disk image with A/UX installed.
[Download the latest release], and then see the [getting started] wiki.
Also check out [screenshots].

View File

@ -7,7 +7,7 @@ CFLAGS = -O3 -ggdb -flto -Wno-deprecated-declarations
DEPS = mc68851.h shoebill.h Makefile macro.pl
NEED_DECODER = cpu dis
NEED_PREPROCESSING = adb fpu mc68851 mem via floppy core_api
NEED_NOTHING = atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool
NEED_NOTHING = atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer
# Object files that can be compiled directly from the source
OBJ_NEED_NOTHING = $(patsubst %,$(TEMP)/%.o,$(NEED_NOTHING))

View File

@ -259,7 +259,7 @@ static void _init_kernel_info(shoebill_config_t *config, scsi_device_t *disks, u
}
// FIXME: I need to stick the auto_id for each nubus card in here
// ki.auto_id[0xb] = 0x5; // Macintosh II video card has an auto_id of 5 (I guess?)
// ki.auto_id[9] = 0x5; // Macintosh II video card has an auto_id of 5 (I guess?)
ki.auto_command = config->aux_autoconfig; // AUTO_NONE/AUTO_CONFIG
@ -553,110 +553,49 @@ uint32_t shoebill_install_video_card(shoebill_config_t *config, uint8_t slotnum,
return 1;
}
static void _do_clut_translation(shoebill_card_video_t *ctx)
uint32_t shoebill_install_tfb_card(shoebill_config_t *config, uint8_t slotnum)
{
uint32_t i;
shoebill_card_tfb_t *ctx;
switch (ctx->depth) {
case 1: {
for (i=0; i < ctx->pixels/8; i++) {
const uint8_t byte = ctx->direct_buf[i];
ctx->temp_buf[i * 8 + 0] = ctx->clut[(byte >> 7) & 1];
ctx->temp_buf[i * 8 + 1] = ctx->clut[(byte >> 6) & 1];
ctx->temp_buf[i * 8 + 2] = ctx->clut[(byte >> 5) & 1];
ctx->temp_buf[i * 8 + 3] = ctx->clut[(byte >> 4) & 1];
ctx->temp_buf[i * 8 + 4] = ctx->clut[(byte >> 3) & 1];
ctx->temp_buf[i * 8 + 5] = ctx->clut[(byte >> 2) & 1];
ctx->temp_buf[i * 8 + 6] = ctx->clut[(byte >> 1) & 1];
ctx->temp_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->direct_buf[i];
ctx->temp_buf[i * 4 + 0] = ctx->clut[(byte >> 6) & 3];
ctx->temp_buf[i * 4 + 1] = ctx->clut[(byte >> 4) & 3];
ctx->temp_buf[i * 4 + 2] = ctx->clut[(byte >> 2) & 3];
ctx->temp_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->direct_buf[i];
ctx->temp_buf[i * 2 + 0] = ctx->clut[(byte >> 4) & 0xf];
ctx->temp_buf[i * 2 + 1] = ctx->clut[(byte >> 0) & 0xf];
}
break;
}
case 8: {
for (i=0; i < ctx->pixels; i++)
ctx->temp_buf[i] = ctx->clut[ctx->direct_buf[i]];
break;
}
case 16: {
uint16_t *direct = (uint16_t*)ctx->direct_buf;
for (i=0; i < ctx->pixels; i++) {
const uint16_t p = ntohs(direct[i]);
video_ctx_color_t tmp;
tmp.r = ((p >> 10) & 31);
tmp.g = (p >> 5) & 31;
tmp.b = (p >> 0) & 31;
ctx->temp_buf[i].r = (tmp.r << 3) | (tmp.r >> 2);
ctx->temp_buf[i].g = (tmp.g << 3) | (tmp.g >> 2);
ctx->temp_buf[i].b = (tmp.b << 3) | (tmp.b >> 2);
}
break;
}
case 32: {
uint32_t *direct = (uint32_t*)ctx->direct_buf, *tmp = (uint32_t*)ctx->temp_buf;
for (i=0; i < ctx->pixels; i++)
tmp[i] = direct[i] >> 8;
// OpenGL wants RGBA
// Apple must be ARGB (which is BGRA, when dereferenced)
break;
}
default:
assert(!"unsupported depth");
if (shoe.slots[slotnum].card_type != card_none) {
sprintf(config->error_msg, "This slot (%u) already has a card\n", slotnum);
return 0;
}
ctx = p_alloc(shoe.pool, sizeof(shoebill_card_tfb_t));
shoe.slots[slotnum].ctx = ctx;
shoe.slots[slotnum].card_type = card_toby_frame_buffer;
shoe.slots[slotnum].connected = 1;
shoe.slots[slotnum].read_func = nubus_tfb_read_func;
shoe.slots[slotnum].write_func = nubus_tfb_write_func;
shoe.slots[slotnum].interrupts_enabled = 1;
nubus_tfb_init(ctx, slotnum);
return 1;
}
shoebill_video_frame_info_t shoebill_get_video_frame(uint8_t slotnum,
_Bool just_params)
{
shoebill_card_video_t *ctx = (shoebill_card_video_t*)shoe.slots[slotnum].ctx;
shoebill_video_frame_info_t result;
assert(shoe.slots[slotnum].card_type == card_shoebill_video); // TBF not supported yet
if (!shoe.running) {
memset(&result, 0, sizeof(result));
return result;
}
result.width = ctx->width;
result.height = ctx->height;
result.scan_width = ctx->scanline_width;
result.depth = ctx->depth;
void *ctx = shoe.slots[slotnum].ctx;
// If caller just wants video parameters...
if (just_params)
return result;
if (shoe.slots[slotnum].card_type == card_toby_frame_buffer)
return nubus_tfb_get_frame(ctx, just_params);
else if (shoe.slots[slotnum].card_type == card_shoebill_video)
return nubus_video_get_frame(ctx, just_params);
_do_clut_translation(ctx);
result.buf = (uint8_t*)ctx->temp_buf;
assert(!"Unknown card type");
memset(&result, 0, sizeof(result));
return result;
}
/*

View File

@ -131,6 +131,8 @@ void shoebill_restart (void);
uint32_t shoebill_install_video_card(shoebill_config_t *config, uint8_t slotnum,
uint16_t width, uint16_t height);
uint32_t shoebill_install_tfb_card(shoebill_config_t *config, uint8_t slotnum);
/* Get a video frame from a particular video card */
shoebill_video_frame_info_t shoebill_get_video_frame(uint8_t slotnum, _Bool just_params);
@ -493,22 +495,6 @@ typedef struct {
uint8_t changed;
} mouse_state_t;
/*typedef struct {
uint8_t *buf_base;
uint32_t buf_size;
uint32_t h_offset; // offset in bytes for each horizontal line
uint8_t vsync;
// unit8_t via_interrupt_flag;
uint8_t depth;
uint8_t clut[256 * 3];
uint32_t clut_idx;
} video_state_t;*/
typedef struct {
// lsb==phase0, msb==L7
uint8_t latch;
@ -592,15 +578,15 @@ typedef struct {
uint32_t pixels;
uint16_t width, height, scanline_width;
uint16_t width, height, scanline_width, line_offset;
uint16_t depth, clut_idx;
double refresh_rate;
} shoebill_card_video_t;
typedef struct {
uint8_t *frame_buffer;
uint8_t *direct_buf, *temp_buf, *clut, *rom;
uint16_t depth, clut_idx, line_offset;
uint8_t vsync;
} shoebill_card_tfb_t;
typedef struct {
@ -1018,9 +1004,11 @@ struct macii_rom_symbols_t {
extern const struct macii_rom_symbols_t macii_rom_symbols[];
// Emulated Toby Frame Buffer nubus card
void nubus_tfb_init(uint8_t slotnum);
void nubus_tfb_init(void *_ctx, uint8_t slotnum);
uint32_t nubus_tfb_read_func(uint32_t, uint32_t, uint8_t);
void nubus_tfb_write_func(uint32_t, uint32_t, uint32_t, uint8_t);
shoebill_video_frame_info_t nubus_tfb_get_frame(shoebill_card_tfb_t *ctx,
_Bool just_params);
// Shoebill Virtual Video Card
void nubus_video_init(void *_ctx, uint8_t slotnum,
@ -1030,6 +1018,8 @@ uint32_t nubus_video_read_func(const uint32_t rawaddr, const uint32_t size,
const uint8_t slotnum);
void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
const uint32_t data, const uint8_t slotnum);
shoebill_video_frame_info_t nubus_video_get_frame(shoebill_card_video_t *ctx,
_Bool just_params);

View File

@ -26,7 +26,6 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <GLUT/glut.h>
#include "shoebill.h"
#define ROM_SIZE 4096
@ -41,45 +40,11 @@ uint8_t macii_video_rom[ROM_SIZE] = {
*/
};
typedef struct {
uint8_t *buf_base;
uint32_t buf_size;
uint32_t clut_idx;
uint32_t h_offset; // offset in bytes for each horizontal line
uint8_t clut[256 * 3];
uint8_t depth;
uint8_t vsync;
uint8_t *gldat;
} tfb_ctx_t;
void nubus_tfb_display_func (void)
static void nubus_tfb_clut_translate(shoebill_card_tfb_t *ctx)
{
uint32_t myw = glutGet(GLUT_WINDOW_WIDTH);
uint32_t myh = glutGet(GLUT_WINDOW_HEIGHT);
uint32_t slotnum, i;
int32_t my_window_id = glutGetWindow();
for (slotnum = 0; slotnum < 16; slotnum++)
if (shoe.slots[slotnum].glut_window_id == my_window_id)
break;
tfb_ctx_t *ctx = (tfb_ctx_t*)shoe.slots[slotnum].ctx;
uint32_t i, gli = 0;
const uint8_t depth = ctx->depth;
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;
for (i=0; i < (1024 * 480);) {
uint8_t code;
@ -91,87 +56,60 @@ void nubus_tfb_display_func (void)
assert(gli < (640 * 480));
if (depth <= 1) {
code = (ctx->buf_base[ctx->h_offset + i/8] & (0x80 >> (i % 8))) != 0;
code = (ctx->direct_buf[ctx->line_offset + i/8] & (0x80 >> (i % 8))) != 0;
code = (code << 7) | 0x7f;
}
else if (depth == 2) {
const uint8_t byte = ctx->buf_base[ctx->h_offset + i/4];
const uint8_t byte = ctx->direct_buf[ctx->line_offset + i/4];
const uint8_t mod = i % 4;
code = (byte << (mod * 2)) & 0xc0;
code |= 0x3f;
}
else if (depth == 4) {
const uint8_t byte = ctx->buf_base[ctx->h_offset + i/2];
const uint8_t byte = ctx->direct_buf[ctx->line_offset + i/2];
const uint8_t mod = i % 2;
code = (byte << (mod * 4)) & 0xf0;
code |= 0x0f;
}
else if (depth == 8) {
code = ctx->buf_base[ctx->h_offset + i];
code = ctx->direct_buf[ctx->line_offset + i];
}
ctx->gldat[gli * 3 + 0] = ctx->clut[code * 3 + 2];
ctx->gldat[gli * 3 + 1] = ctx->clut[code * 3 + 1];
ctx->gldat[gli * 3 + 2] = ctx->clut[code * 3 + 0];
ctx->temp_buf[gli * 4 + 0] = ctx->clut[code * 3 + 2];
ctx->temp_buf[gli * 4 + 1] = ctx->clut[code * 3 + 1];
ctx->temp_buf[gli * 4 + 2] = ctx->clut[code * 3 + 0];
gli++;
i++;
}
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_RGB, GL_UNSIGNED_BYTE, ctx->gldat);
glFlush();
}
void global_mouse_func (int button, int state, int x, int y);
void global_motion_func (int x, int y);
void global_passive_motion_func (int x, int y);
void global_keyboard_up_func (unsigned char c, int x, int y);
void global_keyboard_down_func (unsigned char c, int x, int y);
void global_special_up_func (int special, int x, int y);
void global_special_down_func (int special, int x, int y);
void nubus_tfb_init(uint8_t slotnum)
void nubus_tfb_init(void *_ctx, uint8_t slotnum)
{
tfb_ctx_t *ctx = (tfb_ctx_t*)calloc(sizeof(tfb_ctx_t), 1);
shoebill_card_tfb_t *ctx = (shoebill_card_tfb_t*)_ctx;
ctx->direct_buf = p_alloc(shoe.pool, 512 * 1024 + 4);
ctx->temp_buf = p_alloc(shoe.pool, 640 * 480 * 4);
ctx->rom = p_alloc(shoe.pool, 4096);
ctx->clut = p_alloc(shoe.pool, 256 * 3);
ctx->buf_size = 512 * 1024;
ctx->buf_base = (uint8_t*)calloc(ctx->buf_size, 1);
ctx->depth = 1;
ctx->clut_idx = 786;
ctx->gldat = valloc(480 * 640 * 3);
ctx->line_offset = 0;
memset(ctx->clut, 0x0, 384);
memset(ctx->clut+384, 0xff, 384);
memset(ctx->buf_base, 0xff, ctx->buf_size);
// memcpy(ctx->rom, macii_video_rom, 4096);
// Offset to the TFB sResource
ctx->rom[4096 - 20] = 0;
ctx->rom[4096 - 19] = 0xff;
ctx->rom[4096 - 18] = 0xf0;
ctx->rom[4096 - 17] = 0x14;
// Init CLUT to 1-bit depth
ctx->depth = 1;
memset(ctx->clut, 0x0, 3*128);
memset(ctx->clut + (3*128), 0xff, 3*128);
shoe.slots[slotnum].ctx = ctx;
glutInitWindowSize(640, 480);
shoe.slots[slotnum].glut_window_id = glutCreateWindow("");
glutDisplayFunc(nubus_tfb_display_func);
glutIgnoreKeyRepeat(1);
glutKeyboardFunc(global_keyboard_down_func);
glutKeyboardUpFunc(global_keyboard_up_func);
glutSpecialFunc(global_special_down_func);
glutSpecialUpFunc(global_special_up_func);
glutMouseFunc(global_mouse_func);
glutMotionFunc(global_motion_func);
glutPassiveMotionFunc(global_passive_motion_func);
glShadeModel(GL_FLAT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0.1, 1.0, 0.1, 1.0);
}
uint32_t nubus_tfb_read_func(const uint32_t rawaddr, const uint32_t size, const uint8_t slotnum)
@ -190,7 +128,8 @@ uint32_t nubus_tfb_read_func(const uint32_t rawaddr, const uint32_t size, const
// 1101
// 1110
// 1111 = ROM (repeating 4kb images in S bits)
tfb_ctx_t *ctx = (tfb_ctx_t*)shoe.slots[slotnum].ctx;
//tfb_ctx_t *ctx = (tfb_ctx_t*)shoe.slots[slotnum].ctx;
shoebill_card_tfb_t *ctx = (shoebill_card_tfb_t*)shoe.slots[slotnum].ctx;
const uint32_t addr = rawaddr & 0x000fffff;
uint32_t result = 0;
@ -199,15 +138,15 @@ uint32_t nubus_tfb_read_func(const uint32_t rawaddr, const uint32_t size, const
case 0x0 ... 0x7: { // frame buffer
uint32_t i;
for (i=0; i<size; i++)
result = (result << 8) | ctx->buf_base[addr + i];
result = (result << 8) | ctx->direct_buf[addr + i];
break;
}
case 0xf: { // rom
if ((addr & 3) == 0) {
const uint32_t rom_addr = (addr >> 2) % 4096;
result = macii_video_rom[rom_addr];
slog("nubus_tfb_read_func: returning %x for addr %x (rom_addr=%x)\n", (uint32_t)result, shoe.physical_addr, rom_addr);
result = ctx->rom[rom_addr];
slog("nubus_tfb_read_func: returning %x for addr %x (rom_addr=%x)\n", (uint32_t)result, rawaddr, rom_addr);
}
else
result = 0;
@ -227,14 +166,14 @@ uint32_t nubus_tfb_read_func(const uint32_t rawaddr, const uint32_t size, const
break;
}
else {
slog("nubus_tfb_read_func: unknown read of *0x%08x\n", shoe.physical_addr);
slog("nubus_tfb_read_func: unknown read of *0x%08x\n", rawaddr);
result = 0;
break;
}
}
default: {
slog("nubus_tfb_read_func: unknown read of *0x%08x\n", shoe.physical_addr);
slog("nubus_tfb_read_func: unknown read of *0x%08x\n", rawaddr);
result = 0;
break;
}
@ -246,7 +185,7 @@ uint32_t nubus_tfb_read_func(const uint32_t rawaddr, const uint32_t size, const
void nubus_tfb_write_func(const uint32_t rawaddr, const uint32_t size,
const uint32_t data, const uint8_t slotnum)
{
tfb_ctx_t *ctx = (tfb_ctx_t*)shoe.slots[slotnum].ctx;
shoebill_card_tfb_t *ctx = (shoebill_card_tfb_t*)shoe.slots[slotnum].ctx;
const uint32_t addr = rawaddr & 0x000fffff;
switch (addr >> 16) {
@ -254,7 +193,7 @@ void nubus_tfb_write_func(const uint32_t rawaddr, const uint32_t size,
case 0x0 ... 0x7: { // frame buffer
uint32_t i;
for (i=0; i<size; i++) {
ctx->buf_base[addr + size - (i+1)] = (data >> (8*i)) & 0xFF;
ctx->direct_buf[addr + size - (i+1)] = (data >> (8*i)) & 0xFF;
}
return ;
}
@ -277,19 +216,20 @@ void nubus_tfb_write_func(const uint32_t rawaddr, const uint32_t size,
}
if (addr == 0x8000c) { // horizontal offset
ctx->h_offset = 4 * ((~data) & 0xff);
ctx->line_offset = 4 * ((~data) & 0xff);
return ;
}
else {
slog("video_nubus_set: unknown write to *0x%08x (0x%x)\n", shoe.physical_addr, data);
slog("video_nubus_set: unknown write to *0x%08x (0x%x)\n", rawaddr, data);
return ;
}
}
case 0x9: { // CLUT registers?
if (addr == 0x90018) { // CLUT
uint8_t *clut = (uint8_t*)ctx->clut;
slog("clut[0x%03x (0x%02x+%u)] = 0x%02x\n", ctx->clut_idx, ctx->clut_idx/3, ctx->clut_idx%3, (uint8_t)(data & 0xff));
ctx->clut[ctx->clut_idx] = 255 - (data & 0xff);
clut[ctx->clut_idx] = 255 - (data & 0xff);
ctx->clut_idx = (ctx->clut_idx == 0) ? 767 : ctx->clut_idx-1;
@ -302,20 +242,41 @@ void nubus_tfb_write_func(const uint32_t rawaddr, const uint32_t size,
ctx->clut_idx = clut_dat * 3 + 2;
}
slog("video_nubus_set: unknown write to *0x%08x (0x%x)\n", shoe.physical_addr, data);
slog("video_nubus_set: unknown write to *0x%08x (0x%x)\n", rawaddr, data);
return ;
}
case 0xa: { // clear interrupt for slot 0xa(?) in via2.rega (by setting the appropriate bit)
assert((data & 0xff) == 0);
// shoe.via[1].rega |= 0b00000010;
shoe.via[1].rega |= (1 << (slotnum - 9));
shoe.via[1].rega_input |= (1 << (slotnum - 9));
return ;
}
default: {
slog("video_nubus_set: unknown write to *0x%08x (0x%x)\n", shoe.physical_addr, data);
slog("video_nubus_set: unknown write to *0x%08x (0x%x)\n", rawaddr, data);
return ;
}
}
}
shoebill_video_frame_info_t nubus_tfb_get_frame(shoebill_card_tfb_t *ctx,
_Bool just_params)
{
shoebill_video_frame_info_t result;
result.width = 640;
result.height = 480;
result.scan_width = 640;
result.depth = ctx->depth;
// If caller just wants video parameters...
if (just_params)
return result;
nubus_tfb_clut_translate(ctx);
result.buf = ctx->temp_buf;
return result;
}

View File

@ -54,7 +54,7 @@ typedef struct __attribute__ ((__packed__)) {
uint32_t plane_bytes;
} video_params_t;
uint32_t compute_nubus_crc(uint8_t *rom, uint32_t len)
static uint32_t compute_nubus_crc(uint8_t *rom, uint32_t len)
{
uint32_t i, sum = 0;
@ -88,6 +88,7 @@ void nubus_video_init(void *_ctx, uint8_t slotnum,
ctx->height = height;
ctx->scanline_width = scanline_width;
ctx->pixels = scanline_width * height;
ctx->line_offset = 0;
ctx->direct_buf = p_alloc(shoe.pool, (ctx->pixels+4) * sizeof(video_ctx_color_t));
ctx->temp_buf = p_alloc(shoe.pool, (ctx->pixels+4) * sizeof(video_ctx_color_t));
@ -277,8 +278,100 @@ void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
}
static void _do_clut_translation(shoebill_card_video_t *ctx)
{
uint32_t i;
switch (ctx->depth) {
case 1: {
for (i=0; i < ctx->pixels/8; i++) {
const uint8_t byte = ctx->direct_buf[i];
ctx->temp_buf[i * 8 + 0] = ctx->clut[(byte >> 7) & 1];
ctx->temp_buf[i * 8 + 1] = ctx->clut[(byte >> 6) & 1];
ctx->temp_buf[i * 8 + 2] = ctx->clut[(byte >> 5) & 1];
ctx->temp_buf[i * 8 + 3] = ctx->clut[(byte >> 4) & 1];
ctx->temp_buf[i * 8 + 4] = ctx->clut[(byte >> 3) & 1];
ctx->temp_buf[i * 8 + 5] = ctx->clut[(byte >> 2) & 1];
ctx->temp_buf[i * 8 + 6] = ctx->clut[(byte >> 1) & 1];
ctx->temp_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->direct_buf[i];
ctx->temp_buf[i * 4 + 0] = ctx->clut[(byte >> 6) & 3];
ctx->temp_buf[i * 4 + 1] = ctx->clut[(byte >> 4) & 3];
ctx->temp_buf[i * 4 + 2] = ctx->clut[(byte >> 2) & 3];
ctx->temp_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->direct_buf[i];
ctx->temp_buf[i * 2 + 0] = ctx->clut[(byte >> 4) & 0xf];
ctx->temp_buf[i * 2 + 1] = ctx->clut[(byte >> 0) & 0xf];
}
break;
}
case 8: {
for (i=0; i < ctx->pixels; i++)
ctx->temp_buf[i] = ctx->clut[ctx->direct_buf[i]];
break;
}
case 16: {
uint16_t *direct = (uint16_t*)ctx->direct_buf;
for (i=0; i < ctx->pixels; i++) {
const uint16_t p = ntohs(direct[i]);
video_ctx_color_t tmp;
tmp.r = ((p >> 10) & 31);
tmp.g = (p >> 5) & 31;
tmp.b = (p >> 0) & 31;
ctx->temp_buf[i].r = (tmp.r << 3) | (tmp.r >> 2);
ctx->temp_buf[i].g = (tmp.g << 3) | (tmp.g >> 2);
ctx->temp_buf[i].b = (tmp.b << 3) | (tmp.b >> 2);
}
break;
}
case 32: {
uint32_t *direct = (uint32_t*)ctx->direct_buf, *tmp = (uint32_t*)ctx->temp_buf;
for (i=0; i < ctx->pixels; i++)
tmp[i] = direct[i] >> 8;
// OpenGL wants RGBA
// Apple must be ARGB (which is BGRA, when dereferenced)
break;
}
default:
assert(!"unsupported depth");
}
}
shoebill_video_frame_info_t nubus_video_get_frame(shoebill_card_video_t *ctx,
_Bool just_params)
{
shoebill_video_frame_info_t result;
result.width = ctx->width;
result.height = ctx->height;
result.scan_width = ctx->scanline_width;
result.depth = ctx->depth;
// If caller just wants video parameters...
if (just_params)
return result;
_do_clut_translation(ctx);
result.buf = (uint8_t*)ctx->temp_buf;
return result;
}

View File

@ -1,4 +1,4 @@
uint8_t _video_rom[4096] = {
static uint8_t _video_rom[4096] = {
0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00,
0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x03, 0x84,
0x05, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View File

@ -19,7 +19,7 @@ int main (int argc, char **argv)
assert(fread(rom, 4096, 1, in) == 1);
fprintf(out, "uint8_t _video_rom[4096] = {\n\t");
fprintf(out, "static uint8_t _video_rom[4096] = {\n\t");
for (i=0; i<4095; i++) {
fprintf(out, "0x%02x, ", rom[i]);
if ((i % 8) == 7)

View File

@ -784,9 +784,9 @@ static void _init_keyboard_map (void)
static void _init_glut_video (void)
{
shoebill_card_video_t *ctx = (shoebill_card_video_t*)shoe.slots[9].ctx;
shoebill_video_frame_info_t frame = shoebill_get_video_frame(9, 1);
glutInitWindowSize(ctx->width, ctx->height);
glutInitWindowSize(frame.width, frame.height);
glutCreateWindow("Shoebill");
glutDisplayFunc(_display_func);
glutIgnoreKeyRepeat(1);
@ -812,9 +812,9 @@ static void _init_glut_video (void)
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, ctx->width, 0, ctx->height, -1.0, 1.0);
glOrtho(0, frame.width, 0, frame.height, -1.0, 1.0);
glViewport(0, 0, ctx->width, ctx->height);
glViewport(0, 0, frame.width, frame.height);
}
@ -838,12 +838,12 @@ int main (int argc, char **argv)
config.debug_mode = 1;
config.aux_verbose = 1;
config.ram_size = 8 * 1024 * 1024;
config.ram_size = 16 * 1024 * 1024;
config.aux_kernel_path = "/unix";
config.rom_path = "../priv/macii.rom";
config.scsi_devices[0].path = "../priv/aux_3.0.1.img";
config.scsi_devices[1].path = "../priv/marathon.img";
config.scsi_devices[0].path = "../priv/aux_beta_compacted.img";
//config.scsi_devices[1].path = "../priv/marathon.img";
/*dbg_state.ring_len = 256 * 1024 * 1024;
dbg_state.ring = malloc(dbg_state.ring_len);
@ -856,10 +856,12 @@ int main (int argc, char **argv)
_init_keyboard_map();
shoebill_install_video_card(&config,
/*shoebill_install_video_card(&config,
9, // slotnum
640, // 1024,
480); // 768,
480);*/ // 768,
shoebill_install_tfb_card(&config, 9);
// Start the VIA timer thread
shoebill_start();

22
sdl-gui/lin_build.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/bash
CC=gcc
files=""
for i in adb fpu mc68851 mem via floppy core_api cpu dis; do
perl ../core/macro.pl ../core/$i.c $i.post.c
files="$files $i.post.c"
done
for i in atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer; do
files="$files ../core/$i.c"
done
$CC -O1 ../core/decoder_gen.c -o decoder_gen
./decoder_gen inst .
./decoder_gen dis .
cmd="$CC -O3 -ggdb -flto $files sdl.c -lpthread -lm -lSDL2 -lGL -o shoebill"
echo $cmd
$cmd

View File

@ -195,7 +195,7 @@ struct {
uint32_t height, width;
uint32_t ram_megabytes;
_Bool verbose;
_Bool verbose, use_tfb;
} user_params;
#define equals_arg(name) keylen = strlen(name); value = argv[i]+keylen; if (strncmp((name), argv[i], keylen) == 0)
@ -214,9 +214,16 @@ static void _init_user_params (int argc, char **argv)
user_params.width = 800;
user_params.ram_megabytes = 16;
user_params.verbose = 1;
user_params.use_tfb = 0;
for (i=1; i<argc; i++) {
key = "toby"; // Whether to use the "toby frame buffer" card, instead of the regular shoebill video card
if(strncmp(key, argv[i], strlen(key)) == 0) {
user_params.use_tfb = 1;
continue;
}
key = "ram=";
if (strncmp(key, argv[i], strlen(key)) == 0) {
user_params.ram_megabytes = strtoul(argv[i]+strlen(key), NULL, 10);
@ -284,10 +291,16 @@ static _Bool _setup_shoebill (void)
return 0;
}
shoebill_install_video_card(&config,
9, // slotnum
user_params.width, // 1024,
user_params.height); // 768,
if (user_params.use_tfb) {
shoebill_install_tfb_card(&config, 9);
}
else {
shoebill_install_video_card(&config,
9, // slotnum
user_params.width,
user_params.height);
}
shoebill_start();
return 1;

View File

@ -6,4 +6,4 @@ gcc -O1 ..\core\decoder_gen.c -o decoder_gen
decoder_gen inst .
decoder_gen dis .
gcc -O3 -flto -mno-ms-bitfields sdl.c adb.post.c fpu.post.c mc68851.post.c mem.post.c via.post.c floppy.post.c core_api.post.c cpu.post.c dis.post.c ..\core\atrap_tab.c ..\core\coff.c ..\core\exception.c ..\core\macii_symbols.c ..\core\redblack.c ..\core\scsi.c ..\core\video.c ..\core\filesystem.c ..\core\alloc_pool.c -lmingw32 -lopengl32 -lsdl2main -lsdl2 -o shoebill
gcc -O3 -flto -mno-ms-bitfields sdl.c adb.post.c fpu.post.c mc68851.post.c mem.post.c via.post.c floppy.post.c core_api.post.c cpu.post.c dis.post.c ..\core\atrap_tab.c ..\core\coff.c ..\core\exception.c ..\core\macii_symbols.c ..\core\redblack.c ..\core\scsi.c ..\core\video.c ..\core\filesystem.c ..\core\alloc_pool.c ..\core\toby_frame_buffer.c -lmingw32 -lopengl32 -lsdl2main -lsdl2 -o shoebill