├── .gitignore ├── Force32.mcp ├── Force32.rsrc.bin ├── INIT.c ├── LICENSE ├── README.md ├── ShowInitIcon.c ├── ShowInitIcon.h ├── scripts ├── pack-resources └── unpack-resources ├── xpram.c └── xpram.h /.gitignore: -------------------------------------------------------------------------------- 1 | ._* 2 | Force32 3 | *.SYM 4 | *.rsrc 5 | /Force32 Data/ 6 | -------------------------------------------------------------------------------- /Force32.mcp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesestraws/Force32/7757d61950536e7d0ed8f85b45d53c6f2a0831f8/Force32.mcp -------------------------------------------------------------------------------- /Force32.rsrc.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesestraws/Force32/7757d61950536e7d0ed8f85b45d53c6f2a0831f8/Force32.rsrc.bin -------------------------------------------------------------------------------- /INIT.c: -------------------------------------------------------------------------------- 1 | #include "A4Stuff.h" 2 | #include "SetupA4.h" 3 | #include "ShowInitIcon.h" 4 | #include "xpram.h" 5 | #include 6 | 7 | const int kInitIcon = 128; 8 | const int kYesIcon = 129; 9 | const int kNoIcon = 130; 10 | const int kBadMachineIcon = 131; 11 | 12 | // weAre32Bit reads the 32-bit addressing status out of the xPRAM of the machine 13 | // and returns true if we're currently set up for 32-bit addressing or false if not. 14 | int weAre32Bit() { 15 | char membyte; 16 | read_xpram(&membyte, 0x8A, 1); 17 | 18 | if ((membyte & 5) != 5) { 19 | return false; 20 | } 21 | 22 | return true; 23 | } 24 | 25 | // force32On turns on the two bits that control 32-bit addressing in the xPRAM. 26 | // Note, it dos not sanity check whether this will work or not... 27 | void force32On() { 28 | char membyte; 29 | read_xpram(&membyte, 0x8A, 1); 30 | 31 | // clear bits 1 and 3 32 | membyte = (membyte | 5); 33 | 34 | write_xpram(&membyte, 0x8A, 1); 35 | } 36 | 37 | // restart restarts by jumping to the ROM entry point. See Inside 38 | // Macintosh II, p. 386. Obviously, this never returns. 39 | asm void restart() { 40 | move.l 0x02AE, A0 41 | jmp 0x0A(A0) 42 | } 43 | 44 | 45 | void main(void) 46 | { 47 | long oldA4; 48 | long processorType; 49 | 50 | oldA4 = SetCurrentA4(); 51 | RememberA4(); 52 | 53 | ShowInitIcon(kInitIcon, false); 54 | 55 | // First, check whether we're a 68000: in this case, bail out early, because 56 | // we're doomed regardless. 57 | Gestalt('proc', &processorType); 58 | 59 | if (processorType < 3) { // 3 -> 68020, confusingly 60 | ShowInitIcon(kBadMachineIcon, true); 61 | } else if (weAre32Bit()) { 62 | ShowInitIcon(kYesIcon, true); 63 | } else { 64 | ShowInitIcon(kNoIcon, true); 65 | force32On(); 66 | restart(); 67 | } 68 | 69 | /* restore the a4 world */ 70 | SetA4(oldA4); 71 | } 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Rob Mitchelmore 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Force32 2 | 3 | If you want to use lots of memory on a classic Mac, you need to turn on 32-bit addressing (if the machine supports it). However, this setting is stored in the battery-backed xPRAM. A lot of us run our old Macs without PRAM batteries, simply in the interests of not finding battery leakage all over the place one morning. 4 | 5 | That means that, normally, you have to turn it on, manually, every time you start using the machine. This gets tiresome fast. 6 | 7 | This extension solves that. Put it early in your boot sequence (by putting a few spaces before the name). It will, at load-time, check whether 32-bit addressing is enabled in the PRAM; if it is, it will just display its icon and continue. Otherwise, it will flip the bits that enable 32-bit addressing (see [this page](http://okmij.org/ftp/xPRAM.html) for more details) and start booting all over again. 8 | 9 | Note that it doesn't check whether the Mac can actually do 32-bit addressing before fiddling; so please make sure it can. That said, it will behave properly with MODE32 if you rely on that for 32-bit addressing on Macs without 32-bit clean ROMs. 10 | 11 | ## How to build 12 | 13 | I built this using CodeWarrior Pro 4. Other versions will probably work. It has no external dependencies. It would probably be pretty straightforward to get it to work under THINK C, too, aside from the assembler (though the above linked page has pre-assembled routines that would be a good starting point). 14 | 15 | The resource file is macbinary encoded. If you're unwrapping on OS X you can use the scripts/unpack-resources to generate a resource file from the macbinary, and scripts/pack-resources to turn it back. 16 | 17 | You may need to manually set the file types of the .c and .h files to 'TEXT'. Something like Drop•Attribute will do that for you. 18 | 19 | If you get a "object resource cannot be found" error while building, it's because I forgot to 'Remove Object Code' before uploading a change. Go into the Project menu in CW, then choose 'Remove Object Code', then do a 'Make' again. Then put an issue in and complain at me. 20 | 21 | ## A note on licensing 22 | 23 | It seems kind of absurd to explicitly license something that's basically three pieces of sample code bolted together. My bits are BSD-licensed, but the rest is sample code that has been released with unclear licensing terms. 24 | 25 | ## Acknowledgements 26 | 27 | I wish explicitly to acknolwedge Oleg Kiselyov for their xPRAM work linked above, and the many authors that ShowInitIcon seems to have passed through. 28 | -------------------------------------------------------------------------------- /ShowInitIcon.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheesestraws/Force32/7757d61950536e7d0ed8f85b45d53c6f2a0831f8/ShowInitIcon.c -------------------------------------------------------------------------------- /ShowInitIcon.h: -------------------------------------------------------------------------------- 1 | #ifndef __ShowInitIcon__ 2 | #define __ShowInitIcon__ 3 | 4 | #include 5 | 6 | // Usage: pass the ID of your icon family (ICN#/icl4/icl8) to have it drawn in the right spot. 7 | // If 'advance' is true, the next INIT icon will be drawn to the right of your icon. If it is false, the next INIT icon will overwrite 8 | // yours. You can use it to create animation effects by calling ShowInitIcon several times with 'advance' set to false. 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | pascal void ShowInitIcon (short iconFamilyID, Boolean advance); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif /* __ShowInitIcon__ */ 21 | -------------------------------------------------------------------------------- /scripts/pack-resources: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for i in *.rsrc; do 4 | rm $i.bin 2>/dev/null 5 | macbinary encode $i 6 | done 7 | -------------------------------------------------------------------------------- /scripts/unpack-resources: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for i in *.rsrc.bin; do 4 | FN=`echo $i | sed 's/\.bin$//'` 5 | rm $FN 2>/dev/null 6 | macbinary decode $i 7 | done 8 | -------------------------------------------------------------------------------- /xpram.c: -------------------------------------------------------------------------------- 1 | /* These two routines allow for reading and writing of arbitrary chunks of xPRAM, 2 | the extended PRAM that was introduced after the first generation of Macs. 3 | 4 | Credit for the implementations goes to Oleg Kiselyov, and more information can be found 5 | here: http://okmij.org/ftp/xPRAM.html 6 | */ 7 | 8 | asm void read_xpram(char* buf, const short offset, const short size) { 9 | fralloc 10 | clr.l d0 11 | move.w size, d0 12 | swap d0 13 | move.w offset, d0 14 | movea.l buf, a0 15 | dc.w 0xA051 // _ReadXPRam trap 16 | frfree 17 | rts 18 | } 19 | 20 | asm void write_xpram(char* buf, const short offset, const short size) { 21 | fralloc 22 | clr.l d0 23 | move.w size, d0 24 | swap d0 25 | move.w offset, d0 26 | movea.l buf, a0 27 | dc.w 0xA052 // _WriteXPRam trap 28 | frfree 29 | rts 30 | } -------------------------------------------------------------------------------- /xpram.h: -------------------------------------------------------------------------------- 1 | void read_xpram(char* buf, const short offset, const short size); 2 | void write_xpram(char* buf, const short offset, const short size); 3 | --------------------------------------------------------------------------------