rom: Support variable screen res in MacPlusV3 ROM
This change adds a boatload of ROM patches to alter screen base, resolution, words-per-line, and related variables so that MacOS will function correctly with a framebuffer other than 512x342 (which remains the default). The majority of the patches are actually to make ROM-drawn low-level things (such as disc icons, happy/sad Mac icons/crash hexadecimal info) render right and be positioned correctly. This works up to about 800x600; the limiting factor is patching int16 immediates for certain instructions, meaning a ~64KB framebuffer size is the current limit without more work. The Makefile can now take DISP_WIDTH/DISP_HEIGHT parameters to configure a build. There is no support for dynamic switching, or runtime-selected switching.
This commit is contained in:
parent
183a1472bb
commit
a9be35c7b3
3 changed files with 121 additions and 4 deletions
7
Makefile
7
Makefile
|
|
@ -51,6 +51,11 @@ ifeq ($(DEBUG),1)
|
|||
CFLAGS += -Og -g -ggdb -DDEBUG
|
||||
endif
|
||||
|
||||
# Basic support for changing screen res (with the MacPlusV3 ROM)
|
||||
DISP_WIDTH ?= 512
|
||||
DISP_HEIGHT ?= 342
|
||||
CFLAGS_CFG = -DDISP_WIDTH=$(DISP_WIDTH) -DDISP_HEIGHT=$(DISP_HEIGHT)
|
||||
|
||||
all: main
|
||||
|
||||
$(MUSASHI_SRC): $(MUSASHI)/m68kops.h
|
||||
|
|
@ -61,7 +66,7 @@ $(MUSASHI)/m68kops.c $(MUSASHI)/m68kops.h:
|
|||
prepare: $(MUSASHI)/m68kops.c $(MUSASHI)/m68kops.h
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
$(CC) $(CFLAGS) $(CFLAGS_CFG) -c $< -o $@
|
||||
|
||||
main: $(OBJS)
|
||||
@echo Linking $(OBJS)
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@
|
|||
|
||||
#define PV_SONY_ADDR 0xc00069 /* Magic address for replacement driver PV ops */
|
||||
|
||||
#define DISP_WIDTH 512
|
||||
#define DISP_HEIGHT 342
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RAM accessors
|
||||
//
|
||||
|
|
|
|||
115
src/rom.c
115
src/rom.c
|
|
@ -75,6 +75,9 @@ static uint32_t rom_get_version(uint8_t *rom_base)
|
|||
rom_base[(offset)+0] = ((data) >> 8) & 0xff; \
|
||||
rom_base[(offset)+1] = (data) & 0xff; \
|
||||
} while (0)
|
||||
#define ROM_WR8(offset, data) do { \
|
||||
rom_base[(offset)+0] = (data) & 0xff; \
|
||||
} while (0)
|
||||
|
||||
|
||||
static void rom_patch_plusv3(uint8_t *rom_base)
|
||||
|
|
@ -114,6 +117,118 @@ static void rom_patch_plusv3(uint8_t *rom_base)
|
|||
* we carry on). This avoids wild RAM addrs being accessed.
|
||||
*/
|
||||
#endif
|
||||
|
||||
#if DISP_WIDTH != 512 || DISP_HEIGHT != 342
|
||||
#define SCREEN_SIZE (DISP_WIDTH*DISP_HEIGHT/8)
|
||||
#define SCREEN_DISTANCE_FROM_TOP (SCREEN_SIZE + 0x380)
|
||||
#if (SCREEN_DISTANCE_FROM_TOP >= 65536)
|
||||
#error "rom.c: Screen res patching maths won't work for a screen this large"
|
||||
#endif
|
||||
#define SCREEN_BASE (0x400000-SCREEN_DISTANCE_FROM_TOP)
|
||||
#define SCREEN_BASE_L16 (SCREEN_BASE & 0xffff)
|
||||
#define SBCOORD(x, y) (SCREEN_BASE + ((DISP_WIDTH/8)*(y)) + ((x)/8))
|
||||
|
||||
/* Changing video res:
|
||||
*
|
||||
* Original 512*342 framebuffer is 0x5580 bytes; the screen
|
||||
* buffer lands underneath sound/other buffers at top of mem,
|
||||
* i,e, 0x3fa700 = 0x400000-0x5580-0x380. So any new buffer
|
||||
* will be placed (and read out from for the GUI) at
|
||||
* MEM_TOP-0x380-SCREEN_SIZE.
|
||||
*
|
||||
* For VGA, size is 0x9600 bytes (0x2580 words)
|
||||
*/
|
||||
|
||||
/* We need some space, low down, to create jump-out-and-patch
|
||||
* routines where a patch is too large to put inline. The
|
||||
* TestSoftware check at 0x42 isn't used:
|
||||
*/
|
||||
ROM_WR16(0x42, 0x6000); /* bra */
|
||||
ROM_WR16(0x44, 0x62-0x44); /* offset */
|
||||
/* Now 0x46-0x57 can be used */
|
||||
unsigned int patch_0 = 0x46;
|
||||
ROM_WR16(patch_0 + 0, 0x9bfc); /* suba.l #imm32, A5 */
|
||||
ROM_WR16(patch_0 + 2, 0); /* (Could add more here) */
|
||||
ROM_WR16(patch_0 + 4, SCREEN_DISTANCE_FROM_TOP);
|
||||
ROM_WR16(patch_0 + 6, 0x6000); /* bra */
|
||||
ROM_WR16(patch_0 + 8, 0x3a4 - (patch_0 + 8)); /* Return to 3a4 */
|
||||
|
||||
/* Magic screen-related locations in Mac Plus ROM 4d1f8172:
|
||||
*
|
||||
* 8c : screen base addr (usually 3fa700, now 3f6680)
|
||||
* 148 : screen base addr again
|
||||
* 164 : u32 screen address of crash Mac/critErr hex numbers
|
||||
* 188 : u16 bytes per row (critErr)
|
||||
* 194 : u16 bytes per row (critErr)
|
||||
* 19c : u16 (bytes per row * 6)-1 (critErr)
|
||||
* 1a4 : u32 screen address of critErr twiddly pattern
|
||||
* 1ee : u16 screen sie in words minus one
|
||||
* 3a2 : u16 screen size in bytes (BUT can't patch immediate)
|
||||
* 474 : u16 bytes per row
|
||||
* 494 : u16 screen y
|
||||
* 498 : u16 screen x
|
||||
* a0e : y
|
||||
* a10 : x
|
||||
* ee2 : u16 bytes per row minus 4 (tPutIcon)
|
||||
* ef2 : u16 bytes per row (tPutIcon)
|
||||
* 7e0 : u32 screen address of disk icon (240, 145)
|
||||
* 7f2 : u32 screen address of disk icon's symbol (248, 160)
|
||||
* f0c : u32 screen address of Mac icon (240, 145)
|
||||
* f18 : u32 screen address of Mac icon's face (248, 151)
|
||||
* f36 : u16 bytes per row minus 2 (mPutSymbol)
|
||||
* 1cd1 : hidecursor's bytes per line
|
||||
* 1d48 : xres minus 32 (for cursor rect clipping)
|
||||
* 1d4e : xres minus 32
|
||||
* 1d74 : y
|
||||
* 1d93 : bytes per line (showcursor)
|
||||
* 1e68 : y
|
||||
* 1e6e : x
|
||||
* 1e82 : y
|
||||
*/
|
||||
ROM_WR16(0x8c, SCREEN_BASE_L16);
|
||||
ROM_WR16(0x148, SCREEN_BASE_L16);
|
||||
ROM_WR32(0x164, SBCOORD(DISP_WIDTH/2 - (48/2), DISP_HEIGHT/2 + 8));
|
||||
ROM_WR16(0x188, DISP_WIDTH/8);
|
||||
ROM_WR16(0x194, DISP_WIDTH/8);
|
||||
ROM_WR16(0x19c, (6*DISP_WIDTH/8)-1);
|
||||
ROM_WR32(0x1a4, SBCOORD(DISP_WIDTH/2 - 8, DISP_HEIGHT/2 + 8 + 8));
|
||||
ROM_WR16(0x1ee, (SCREEN_SIZE/4)-1);
|
||||
|
||||
ROM_WR32(0xf0c, SBCOORD(DISP_WIDTH/2 - 16, DISP_HEIGHT/2 - 26));
|
||||
ROM_WR32(0xf18, SBCOORD(DISP_WIDTH/2 - 8, DISP_HEIGHT/2 - 20));
|
||||
ROM_WR32(0x7e0, SBCOORD(DISP_WIDTH/2 - 16, DISP_HEIGHT/2 - 26));
|
||||
ROM_WR32(0x7f2, SBCOORD(DISP_WIDTH/2 - 8, DISP_HEIGHT/2 - 11));
|
||||
|
||||
/* Patch "SubA #$5900, A5" to subtract 0x9880.
|
||||
* However... can't just patch the int16 immediate, as that's
|
||||
* sign-extended (and we end up with a subtract-negative,
|
||||
* i.e. an add). There isn't space here to turn it into sub.l
|
||||
* so add some rigamarole to branch to some bytes stolen at
|
||||
* patch_0 up above.
|
||||
*/
|
||||
ROM_WR16(0x3a0, 0x6000); /* bra */
|
||||
ROM_WR16(0x3a2, patch_0 - 0x3a2); /* ...to patch0, returns at 0x3a4 */
|
||||
|
||||
ROM_WR16(0x474, DISP_WIDTH/8);
|
||||
ROM_WR16(0x494, DISP_HEIGHT);
|
||||
ROM_WR16(0x498, DISP_WIDTH);
|
||||
ROM_WR16(0xa0e, DISP_HEIGHT); /* copybits? */
|
||||
ROM_WR16(0xa10, DISP_WIDTH);
|
||||
ROM_WR16(0xee2, (DISP_WIDTH/8)-4); /* tPutIcon bytes per row, minus 4 */
|
||||
ROM_WR16(0xef2, DISP_WIDTH/8); /* tPutIcon bytes per row */
|
||||
ROM_WR16(0xf36, (DISP_WIDTH/8)-2); /* tPutIcon bytes per row, minus 2 */
|
||||
ROM_WR8(0x1cd1, DISP_WIDTH/8); /* hidecursor */
|
||||
ROM_WR16(0x1d48, DISP_WIDTH-32); /* 1d46+2 was originally 512-32 rite? */
|
||||
ROM_WR16(0x1d4e, DISP_WIDTH-32); /* 1d4c+2 is 480, same */
|
||||
ROM_WR16(0x1d6e, DISP_HEIGHT-16); /* showcursor (YESS fixed Y crash bug!) */
|
||||
ROM_WR16(0x1d74, DISP_HEIGHT); /* showcursor */
|
||||
ROM_WR8(0x1d93, DISP_WIDTH/8); /* showcursor */
|
||||
ROM_WR16(0x1e68, DISP_HEIGHT); /* mScrnSize */
|
||||
ROM_WR16(0x1e6e, DISP_WIDTH); /* mScrnSize */
|
||||
ROM_WR16(0x1e82, DISP_HEIGHT); /* tScrnBitMap */
|
||||
|
||||
/* FIXME: Welcome To Macintosh is drawn at the wrong position. Find where that's done. */
|
||||
#endif
|
||||
}
|
||||
|
||||
int rom_patch(uint8_t *rom_base)
|
||||
|
|
|
|||
Loading…
Reference in a new issue