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:
parent
42fd2a0b4e
commit
f051d42597
|
@ -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].
|
||||
|
|
|
@ -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))
|
||||
|
|
111
core/core_api.c
111
core/core_api.c
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
99
core/video.c
99
core/video.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue