├── .gitignore
├── CMakeLists.txt
├── README.md
├── build.sh
├── lib
├── OpenGLLibraryStub
├── OpenGLMemoryStub
└── OpenGLUtilityStub
└── src
├── console
├── Console.cpp
├── Console.hpp
├── ConsoleWindow.cpp
├── ConsoleWindow.hpp
├── InitConsole.cpp
└── MacUtils.h
├── detection
├── 68kextras.cpp
├── battery.cpp
├── cpu.cpp
├── disk.cpp
├── functions.cpp
├── functions.hpp
├── gestalt.cpp
├── gpu.cpp
├── memory.cpp
├── misc.cpp
├── os.cpp
├── rom.cpp
├── user.cpp
└── xpostcode
│ ├── CPUDevice.cpp
│ └── CPUDevice.h
├── logo.hpp
└── os9fetch.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | *build*/
3 | *.bin
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.0)
2 |
3 | project(os9fetch LANGUAGES C CXX)
4 |
5 |
6 | # compile flags
7 | add_compile_options(${COMPILE_FLAGS})
8 | add_compile_definitions(
9 | _GNU_SOURCE
10 | CONFIG_BIGNUM
11 | CONFIG_VERSION=${QUICKJS_VERSION}
12 | CONFIG_AGENT=0
13 | )
14 |
15 | set(QJSC_CONFIG -DCONFIG_PREFIX="/usr/local" -DCONFIG_LTO)
16 | set(QJSC_EXE "${EXECUTABLE_OUTPUT_PATH}/qjsc")
17 | set(QJS_CONFIG ${QJSC_CONFIG} -DCONFIG_CC="clang")
18 |
19 |
20 | ###############################################################################
21 | ## file globbing ##############################################################
22 | ###############################################################################
23 |
24 | # these instructions search the directory tree when CMake is
25 | # invoked and put all files that match the pattern in the variables
26 | # `sources` and `data`
27 | file(GLOB_RECURSE sources
28 | src/**/**/**/*.c src/**/**/**/*.h src/**/**/**/*.cpp src/**/**/**/*.hpp
29 | src/**/**/*.c src/**/**/*.h src/**/**/*.cpp src/**/**/*.hpp
30 | src/**/*.c src/**/*.h src/**/*.cpp src/**/*.hpp
31 | src/*.c src/*.h src/*.cpp src/*.hpp
32 | )
33 | file(GLOB_RECURSE data resources/*)
34 | # you can use set(sources src/main.cpp) etc if you don't want to
35 | # use globbing to find files automatically
36 |
37 | ###############################################################################
38 | ## target definitions #########################################################
39 | ###############################################################################
40 |
41 | # add the data to the target, so it becomes visible in some IDE
42 |
43 | if(CMAKE_SYSTEM_NAME MATCHES Retro)
44 | add_application(os9fetch ${sources} ${data})
45 | else()
46 | add_executable(os9fetch ${sources} ${data})
47 | endif()
48 | target_link_directories(os9fetch PUBLIC ${CMAKE_SOURCE_DIR}/lib )
49 |
50 | set_property(TARGET os9fetch PROPERTY CXX_STANDARD 20)
51 |
52 | # just for os9fetch add some compiler flags
53 | target_compile_options(os9fetch PUBLIC -std=c++20 -Wall -Wfloat-conversion)
54 |
55 | set_target_properties(os9fetch PROPERTIES COMPILE_OPTIONS -ffunction-sections)
56 | #target_link_libraries(os9fetch "${RETRO68_ROOT}/InterfaceAndLibraries/Libraries/StubLibraries/ThreadsLib")
57 |
58 | #target_link_libraries( os9fetch ThreadsLib)
59 |
60 | if(PLATFORM MATCHES retro68)
61 | add_compile_definitions(FOR_68K)
62 | endif()
63 |
64 | if(PLATFORM MATCHES retroppc)
65 | add_compile_definitions(FOR_PPC)
66 | set_target_properties(os9fetch PROPERTIES COMPILE_FLAGS "-ffunction-sections -mcpu=601 -O3 -Wall -Wextra -Wno-unused-parameter")
67 | set_target_properties(os9fetch PROPERTIES LINK_FLAGS "-Wl,-gc-sections")
68 | target_link_libraries( os9fetch PowerMgrLib)
69 | target_link_libraries( os9fetch NameRegistryLib)
70 | target_link_libraries( os9fetch OpenGL)
71 | endif()
72 |
73 |
74 | include_directories( "${RETRO68_TOOLCHAIN}universal/CIncludes/")
75 | message(STATUS "Making for ${CMAKE_SYSTEM_NAME}")
76 | if(CMAKE_SYSTEM_NAME MATCHES Retro68)
77 | set_target_properties(os9fetch PROPERTIES LINK_FLAGS "-Wl,--mac-strip-macsbug")
78 | endif()
79 |
80 | # this copies all resource files in the build directory
81 | # we need this, because we want to work with paths relative to the executable
82 | file(COPY ${data} DESTINATION resources)
83 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | |
7 |
8 | PowerFetch
9 | Neofetch clone for Classic Mac based computers, so that you can show off your Macs in the same endearingly stupid way that modern Linux users get to! It can be run going back to System 4.0, on both PowerPC and 68k!
10 | |
11 |
12 |
13 |
14 |
15 | # Compiling
16 |
17 | Install [Retro68](https://github.com/autc04/Retro68), then set `$RETRO68_TOOLCHAIN_PATH` to your toolchain path and `$RETRO68_INSTALL_PATH` to the path of the cloned repo. Then, run `build.sh` to build for both 68k and PowerPC.
18 |
19 | The resulting file will be the stuffit file `os9fetch.bin` (the old name of the project) in either the `build-68k` or `build-PowerPC` folder.
20 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | function make_for() {
2 | echo "=================="
3 | echo "Making $1"
4 | echo "=================="
5 | mkdir -p build-$1
6 | cd build-$1
7 | cmd="cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_QJS_LIBC=OFF -DPLATFORM=$2 -DRETRO68_ROOT=$RETRO68_TOOLCHAIN_PATH -DCMAKE_TOOLCHAIN_FILE=$RETRO68_INSTALL_PATH/cmake/$2.toolchain.cmake.in"
8 | cmd2="make -j$(nproc)"
9 | $cmd && $cmd2
10 | status=$?
11 | cd ..
12 | return $status
13 | }
14 |
15 | make_for "68k" "retro68" && make_for "PowerPC" "retroppc"
--------------------------------------------------------------------------------
/lib/OpenGLLibraryStub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PowerMacTools/PowerFetch/82ef53f5a1dcd80f8d14f6573c6ca4a2e0da7d08/lib/OpenGLLibraryStub
--------------------------------------------------------------------------------
/lib/OpenGLMemoryStub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PowerMacTools/PowerFetch/82ef53f5a1dcd80f8d14f6573c6ca4a2e0da7d08/lib/OpenGLMemoryStub
--------------------------------------------------------------------------------
/lib/OpenGLUtilityStub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PowerMacTools/PowerFetch/82ef53f5a1dcd80f8d14f6573c6ca4a2e0da7d08/lib/OpenGLUtilityStub
--------------------------------------------------------------------------------
/src/console/Console.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
3 |
4 | This file is part of Retro68.
5 |
6 | Retro68 is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Retro68 is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | Under Section 7 of GPL version 3, you are granted additional
17 | permissions described in the GCC Runtime Library Exception, version
18 | 3.1, as published by the Free Software Foundation.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with Retro68. If not, see .
22 | */
23 |
24 | #include "Console.hpp"
25 | #include "MacUtils.h"
26 | #include
27 | #include
28 |
29 | #include
30 |
31 | using namespace retro;
32 |
33 | const char BEL = 7;
34 | const char MAX_LEN = 250;
35 |
36 | Console *Console::currentInstance = NULL;
37 |
38 | Attributes::Attributes(void)
39 | {
40 | reset();
41 | }
42 | void Attributes::reset(void)
43 | {
44 | cBold = false;
45 | cUnderline = false;
46 | cItalic = false;
47 | }
48 |
49 | bool Attributes::isBold(void) const
50 | {
51 | return cBold;
52 | }
53 |
54 | bool Attributes::isUnderline(void) const
55 | {
56 | return cUnderline;
57 | }
58 |
59 | bool Attributes::isItalic(void) const
60 | {
61 | return cItalic;
62 | }
63 |
64 | void Attributes::setBold(const bool v)
65 | {
66 | cBold = v;
67 | }
68 |
69 | void Attributes::setItalic(const bool v)
70 | {
71 | cItalic = v;
72 | }
73 |
74 | void Attributes::setUnderline(const bool v)
75 | {
76 | cUnderline = v;
77 | }
78 |
79 | inline bool operator==(const Attributes &lhs, const Attributes &rhs)
80 | {
81 | return lhs.isBold() == rhs.isBold() && lhs.isUnderline() == rhs.isUnderline() && lhs.isItalic() == rhs.isItalic();
82 | }
83 |
84 | inline bool operator!=(const Attributes &lhs, const Attributes &rhs)
85 | {
86 | return !(lhs == rhs);
87 | }
88 |
89 | inline bool operator==(const AttributedChar &lhs, const AttributedChar &rhs)
90 | {
91 | return lhs.c == rhs.c && lhs.attrs == rhs.attrs;
92 | }
93 |
94 | inline bool operator!=(const AttributedChar &lhs, const AttributedChar &rhs)
95 | {
96 | return !(lhs == rhs);
97 | }
98 |
99 | namespace
100 | {
101 | class FontSetup
102 | {
103 | short saveFont, saveSize, saveFace;
104 |
105 | public:
106 | FontSetup()
107 | {
108 | #if TARGET_API_MAC_CARBON
109 | GrafPtr port;
110 | GetPort(&port);
111 | saveFont = GetPortTextFont(port);
112 | saveSize = GetPortTextSize(port);
113 | #else
114 | saveFont = qd.thePort->txFont;
115 | saveSize = qd.thePort->txSize;
116 | saveFace = qd.thePort->txFace;
117 | #endif
118 | TextFont(kFontIDMonaco);
119 | TextSize(9);
120 | TextFace(normal);
121 | }
122 |
123 | ~FontSetup()
124 | {
125 | TextFont(saveFont);
126 | TextSize(saveSize);
127 | TextFace(saveFace);
128 | }
129 | };
130 | }
131 |
132 | Console::Console()
133 | {
134 | }
135 |
136 | Console::Console(GrafPtr port, Rect r)
137 | {
138 | Init(port, r);
139 | }
140 |
141 | Console::~Console()
142 | {
143 | if (currentInstance == this)
144 | currentInstance = NULL;
145 | }
146 |
147 | void Console::Init(GrafPtr port, Rect r)
148 | {
149 | consolePort = port;
150 | bounds = r;
151 |
152 | PortSetter setport(consolePort);
153 | FontSetup fontSetup;
154 |
155 | cellSizeY = 12;
156 | cellSizeX = CharWidth('M');
157 |
158 | rows = (bounds.bottom - bounds.top) / cellSizeY;
159 | cols = (bounds.right - bounds.left) / cellSizeX;
160 |
161 | chars = std::vector(rows * cols, AttributedChar(' ', currentAttr));
162 |
163 | onscreen = chars;
164 |
165 | cursorX = cursorY = 0;
166 | sequenceState = State::noSequence;
167 | }
168 |
169 | void Console::SetAttributes(Attributes aa)
170 | {
171 | TextFace(aa.isBold() ? bold + condense : 0 + aa.isUnderline() ? underline
172 | : 0 + aa.isItalic() ? italic
173 | : 0);
174 | }
175 |
176 | Rect Console::CellRect(short x, short y)
177 | {
178 | return {(short)(bounds.top + y * cellSizeY), (short)(bounds.left + x * cellSizeX),
179 | (short)(bounds.top + (y + 1) * cellSizeY), (short)(bounds.left + (x + 1) * cellSizeX)};
180 | }
181 | void Console::DrawCell(short x, short y, bool erase)
182 | {
183 | Rect r = CellRect(x, y);
184 |
185 | if (cursorDrawn)
186 | {
187 | if (y == cursorY && x == cursorX)
188 | {
189 | erase = true;
190 | cursorDrawn = false;
191 | }
192 | }
193 |
194 | if (erase)
195 | EraseRect(&r);
196 | MoveTo(r.left, r.bottom - 2);
197 | DrawChar(chars[y * cols + x].c);
198 | }
199 |
200 | void Console::DrawCells(short x1, short x2, short y, bool erase)
201 | {
202 | Rect r = {(short)(bounds.top + y * cellSizeY), (short)(bounds.left + x1 * cellSizeX),
203 | (short)(bounds.top + (y + 1) * cellSizeY), (short)(bounds.left + x2 * cellSizeX)};
204 | if (cursorDrawn)
205 | {
206 | if (y == cursorY && x1 <= cursorX && x2 > cursorX)
207 | {
208 | erase = true;
209 | cursorDrawn = false;
210 | }
211 | }
212 |
213 | if (erase)
214 | EraseRect(&r);
215 | MoveTo(r.left, r.bottom - 2);
216 |
217 | Attributes a = chars[y * cols + x1].attrs;
218 | SetAttributes(a);
219 | for (int i = x1; i < x2; ++i)
220 | {
221 | if (a != chars[y * cols + i].attrs)
222 | {
223 | a = chars[y * cols + i].attrs;
224 | SetAttributes(a);
225 | }
226 | DrawChar(chars[y * cols + i].c);
227 | }
228 | }
229 |
230 | void Console::Draw(Rect r)
231 | {
232 | if (!consolePort)
233 | return;
234 | PortSetter setport(consolePort);
235 | FontSetup fontSetup;
236 |
237 | SectRect(&r, &bounds, &r);
238 |
239 | short minRow = std::max(0, (r.top - bounds.top) / cellSizeY);
240 | short maxRow = std::min((int)rows, (r.bottom - bounds.top + cellSizeY - 1) / cellSizeY);
241 |
242 | short minCol = std::max(0, (r.left - bounds.left) / cellSizeX);
243 | short maxCol = std::min((int)cols, (r.right - bounds.left + cellSizeX - 1) / cellSizeX);
244 |
245 | EraseRect(&r);
246 | for (short row = minRow; row < maxRow; ++row)
247 | {
248 | DrawCells(minCol, maxCol, row, false);
249 | }
250 | if (cursorDrawn)
251 | {
252 | Rect cursor = CellRect(cursorX, cursorY);
253 | InvertRect(&cursor);
254 | }
255 | onscreen = chars;
256 | }
257 |
258 | void Console::ScrollUp(short n)
259 | {
260 | cursorY--;
261 | std::copy(chars.begin() + cols, chars.end(), chars.begin());
262 | std::fill(chars.end() - cols, chars.end(), AttributedChar(' ', currentAttr));
263 | std::copy(onscreen.begin() + cols, onscreen.end(), onscreen.begin());
264 | std::fill(onscreen.end() - cols, onscreen.end(), AttributedChar(' ', currentAttr));
265 | RgnHandle rgn = NewRgn();
266 | ScrollRect(&bounds, 0, -cellSizeY, rgn);
267 | DisposeRgn(rgn);
268 | dirtyRect.top = dirtyRect.top > 0 ? dirtyRect.top - 1 : 0;
269 | dirtyRect.bottom = dirtyRect.bottom > 0 ? dirtyRect.bottom - 1 : 0;
270 | }
271 |
272 | bool Console::ProcessEscSequence(char c)
273 | {
274 | switch (sequenceState)
275 | {
276 | case State::noSequence:
277 | return false; // Break is not needed there.
278 | case State::waitingForSequenceStart:
279 | if (c == '[')
280 | sequenceState = State::waitingForControlSequence;
281 | else if (c == ']')
282 | sequenceState = State::waitingForOSCStart;
283 | else
284 | sequenceState = State::noSequence; // Unrecognized sequence
285 | break;
286 | case State::waitingForControlSequence:
287 | sequenceState = State::waitingForM;
288 | switch (c)
289 | {
290 | case '0': // Normal character
291 | currentAttr.reset();
292 | break;
293 | case '1': // Bold
294 | currentAttr.setBold(true);
295 | break;
296 | case '3': // Italic
297 | currentAttr.setItalic(true);
298 | break;
299 | case '4': // Underline
300 | currentAttr.setUnderline(true);
301 | break;
302 | default:
303 | sequenceState = State::noSequence; // Unrecognized sequence
304 | }
305 | break;
306 | case State::waitingForM:
307 | if (c == 'm')
308 | sequenceState = State::noSequence; // Normal end of sequence
309 | else
310 | sequenceState = State::noSequence; // Unrecognized sequence (but we end it anyway!)
311 | break;
312 | case State::waitingForOSCStart:
313 | if (c == '0')
314 | sequenceState = State::waitingForSemicolon;
315 | else
316 | sequenceState = State::noSequence; // Normal end of sequence
317 | break;
318 | case State::waitingForSemicolon:
319 | if (c == ';')
320 | {
321 | sequenceState = State::inWindowName;
322 | windowName = "";
323 | }
324 | else
325 | sequenceState = State::noSequence; // Normal end of sequence
326 | break;
327 | case State::inWindowName:
328 | if (c == BEL)
329 | {
330 | setWindowName(std::move(windowName));
331 | sequenceState = State::noSequence; // Normal end of sequence
332 | }
333 | else
334 | {
335 | if (windowName.size() < MAX_LEN) // Ignore subsequent characters
336 | windowName += c;
337 | }
338 | break;
339 | default:
340 | sequenceState = State::noSequence;
341 | break;
342 | }
343 | return true;
344 | }
345 |
346 | long colors[]{
347 | greenColor,
348 | greenColor,
349 | greenColor,
350 | greenColor,
351 | greenColor,
352 | greenColor,
353 | yellowColor,
354 | yellowColor,
355 | redColor,
356 | redColor,
357 | redColor,
358 | redColor,
359 | magentaColor,
360 | magentaColor,
361 | blueColor,
362 | blueColor,
363 | greenColor,
364 | };
365 |
366 | int curColor = 0;
367 |
368 | void Console::PutCharNoUpdate(char c)
369 | {
370 | if (ProcessEscSequence(c))
371 | return;
372 |
373 | InvalidateCursor();
374 | switch (c)
375 | {
376 | case '\033': // Begin of an ANSI escape sequence
377 | sequenceState = State::waitingForSequenceStart;
378 | break;
379 | case '\r':
380 | cursorX = 0;
381 | break;
382 | case '\n':
383 | cursorY++;
384 | cursorX = 0;
385 | if (cursorY >= rows)
386 | ScrollUp();
387 |
388 | break;
389 | default:
390 | chars[cursorY * cols + cursorX].c = c;
391 | chars[cursorY * cols + cursorX].attrs = currentAttr;
392 |
393 | if (dirtyRect.right == 0)
394 | {
395 | dirtyRect.right = (dirtyRect.left = cursorX) + 1;
396 | dirtyRect.bottom = (dirtyRect.top = cursorY) + 1;
397 | }
398 | else
399 | {
400 | dirtyRect.left = std::min(dirtyRect.left, cursorX);
401 | dirtyRect.top = std::min(dirtyRect.top, cursorY);
402 | dirtyRect.right = std::max(dirtyRect.right, short(cursorX + 1));
403 | dirtyRect.bottom = std::max(dirtyRect.bottom, short(cursorY + 1));
404 | }
405 |
406 | cursorX++;
407 | if (cursorX >= cols)
408 | PutCharNoUpdate('\n');
409 | }
410 | }
411 |
412 | void Console::Update()
413 | {
414 | PortSetter setport(consolePort);
415 | FontSetup fontSetup;
416 |
417 | BackColor(blackColor);
418 | ForeColor(whiteColor);
419 |
420 | for (short row = dirtyRect.top; row < dirtyRect.bottom; ++row)
421 | {
422 | short start = -1;
423 | bool needclear = false;
424 | for (short col = dirtyRect.left; col < dirtyRect.right; ++col)
425 | {
426 | AttributedChar old = onscreen[row * cols + col];
427 | if (chars[row * cols + col] != old)
428 | {
429 | if (start == -1)
430 | start = col;
431 | if (old.c != ' ')
432 | needclear = true;
433 | onscreen[row * cols + col] = chars[row * cols + col];
434 | }
435 | else
436 | {
437 |
438 | if (start != -1)
439 | DrawCells(start, col, row, needclear);
440 | start = -1;
441 | needclear = false;
442 | }
443 | }
444 | if (start != -1)
445 | DrawCells(start, dirtyRect.right, row, needclear);
446 | }
447 | dirtyRect = Rect();
448 |
449 | if (cursorVisible != cursorDrawn)
450 | {
451 | Rect r = CellRect(cursorX, cursorY);
452 | if (cursorDrawn)
453 | DrawCell(cursorX, cursorY, true);
454 | else
455 | InvertRect(&r);
456 | cursorDrawn = !cursorDrawn;
457 | }
458 |
459 | #if TARGET_API_MAC_CARBON
460 | QDFlushPortBuffer(consolePort, NULL);
461 | #endif
462 | }
463 |
464 | void Console::putch(char c)
465 | {
466 | if (!rows)
467 | return;
468 | PutCharNoUpdate(c);
469 | Update();
470 | }
471 |
472 | void Console::write(const char *p, int n)
473 | {
474 | if (!rows)
475 | return;
476 |
477 | for (int i = 0; i < n; i++)
478 | Console::currentInstance->PutCharNoUpdate(*p++);
479 | Update();
480 | }
481 |
482 | std::string Console::ReadLine()
483 | {
484 | if (!consolePort)
485 | return "";
486 |
487 | std::string buffer;
488 | char c;
489 |
490 | do
491 | {
492 | c = WaitNextChar();
493 | if (!c)
494 | {
495 | eof = true;
496 | return "";
497 | }
498 |
499 | if (c == '\r')
500 | c = '\n';
501 |
502 | if (c == '\b')
503 | {
504 | if (buffer.size())
505 | {
506 | InvalidateCursor();
507 | cursorX--;
508 | PutCharNoUpdate(' ');
509 | cursorX--;
510 | Update();
511 |
512 | buffer.resize(buffer.size() - 1);
513 | }
514 |
515 | continue;
516 | }
517 |
518 | putch(c);
519 | buffer.append(1, c);
520 | } while (c != '\n');
521 | return buffer;
522 | }
523 |
524 | void Console::InvalidateCursor()
525 | {
526 | if (cursorDrawn)
527 | {
528 | PortSetter setport(consolePort);
529 | DrawCell(cursorX, cursorY, true);
530 | cursorDrawn = false;
531 | }
532 | }
533 |
534 | void Console::Idle()
535 | {
536 | long ticks = TickCount();
537 | if (ticks - blinkTicks > 60)
538 | {
539 | cursorVisible = !cursorVisible;
540 | blinkTicks = ticks;
541 | Update();
542 | }
543 | }
544 |
545 | void Console::Reshape(Rect newBounds)
546 | {
547 | if (!consolePort)
548 | return;
549 |
550 | bounds = newBounds;
551 |
552 | short newRows = (bounds.bottom - bounds.top) / cellSizeY;
553 | short newCols = (bounds.right - bounds.left) / cellSizeX;
554 |
555 | short upshift = 0;
556 | if (cursorY >= newRows)
557 | {
558 | upshift = cursorY - (newRows - 1);
559 |
560 | InvalidateCursor();
561 | cursorY = std::max(newRows - 1, 0);
562 | }
563 |
564 | std::vector newChars(newRows * newCols, AttributedChar(' ', currentAttr));
565 | for (short row = 0; row < newRows && row + upshift < rows; row++)
566 | {
567 | AttributedChar *src = &chars[(row + upshift) * cols];
568 | AttributedChar *dst = &newChars[row * newCols];
569 | std::copy(src, src + std::min(cols, newCols), dst);
570 | }
571 | chars.swap(newChars);
572 |
573 | onscreen = newChars;
574 |
575 | rows = newRows;
576 | cols = newCols;
577 |
578 | dirtyRect = Rect{0, 0, rows, cols};
579 | EraseRect(&newBounds);
580 | Update();
581 | Draw(newBounds);
582 | }
583 |
584 | char Console::WaitNextChar()
585 | {
586 | return 0;
587 | }
--------------------------------------------------------------------------------
/src/console/Console.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
3 |
4 | This file is part of Retro68.
5 |
6 | Retro68 is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Retro68 is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | Under Section 7 of GPL version 3, you are granted additional
17 | permissions described in the GCC Runtime Library Exception, version
18 | 3.1, as published by the Free Software Foundation.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with Retro68. If not, see .
22 | */
23 | #ifndef RETRO68_CONSOLE_H_
24 | #define RETRO68_CONSOLE_H_
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | namespace retro
31 | {
32 | void InitConsole();
33 |
34 | class Attributes
35 | {
36 | public:
37 | bool isBold(void) const;
38 | bool isUnderline(void) const;
39 | bool isItalic(void) const;
40 |
41 | void setBold(const bool v);
42 | void setUnderline(const bool v);
43 | void setItalic(const bool v);
44 |
45 | Attributes(void);
46 | void reset(void);
47 |
48 | private:
49 | bool cBold;
50 | bool cUnderline;
51 | bool cItalic;
52 | };
53 |
54 | class AttributedChar
55 | {
56 | public:
57 | char c;
58 | Attributes attrs;
59 | AttributedChar(char cc, Attributes aa)
60 | {
61 | c = cc;
62 | attrs = aa;
63 | }
64 | };
65 |
66 | enum class State
67 | {
68 | noSequence,
69 | waitingForSequenceStart,
70 | waitingForControlSequence,
71 | waitingForM,
72 | waitingForOSCStart,
73 | waitingForSemicolon,
74 | inWindowName
75 | };
76 |
77 | class Console
78 | {
79 | public:
80 | Console();
81 | Console(GrafPtr port, Rect r);
82 | ~Console();
83 |
84 | void Reshape(Rect newBounds);
85 |
86 | void Draw(Rect r);
87 | void Draw() { Draw(bounds); }
88 | void putch(char c);
89 |
90 | void write(const char *s, int n);
91 | std::string ReadLine();
92 |
93 | static Console *currentInstance;
94 |
95 | short GetRows() const { return rows; }
96 | short GetCols() const { return cols; }
97 |
98 | virtual void setWindowName(std::string newName) {};
99 |
100 | void Idle();
101 |
102 | bool IsEOF() const { return eof; }
103 | void Update();
104 | void PutCharNoUpdate(char c);
105 |
106 | private:
107 | State sequenceState;
108 | std::string windowName;
109 | GrafPtr consolePort = nullptr;
110 | Rect bounds;
111 | Attributes currentAttr;
112 |
113 | std::vector chars, onscreen;
114 |
115 | short cellSizeX;
116 | short cellSizeY;
117 |
118 | short rows = 0, cols = 0;
119 |
120 | short cursorX, cursorY;
121 |
122 | Rect dirtyRect = {};
123 |
124 | long blinkTicks = 0;
125 | bool cursorDrawn = false;
126 | bool cursorVisible = true;
127 | bool eof = false;
128 |
129 | short CalcStartX(short x, short y);
130 | Rect CellRect(short x, short y);
131 | void DrawCell(short x, short y, bool erase = true);
132 | void DrawCells(short x1, short x2, short y, bool erase = true);
133 | void ScrollUp(short n = 1);
134 | bool ProcessEscSequence(char c);
135 | void SetAttributes(Attributes aa);
136 |
137 | void InvalidateCursor();
138 |
139 | virtual char WaitNextChar();
140 |
141 | protected:
142 | void Init(GrafPtr port, Rect r);
143 | };
144 |
145 | }
146 |
147 | #endif /* RETRO68_CONSOLE_H_ */
--------------------------------------------------------------------------------
/src/console/ConsoleWindow.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
3 |
4 | This file is part of Retro68.
5 |
6 | Retro68 is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Retro68 is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | Under Section 7 of GPL version 3, you are granted additional
17 | permissions described in the GCC Runtime Library Exception, version
18 | 3.1, as published by the Free Software Foundation.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with Retro68. If not, see .
22 | */
23 |
24 | #include "ConsoleWindow.hpp"
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | using namespace retro;
31 |
32 | namespace
33 | {
34 | std::unordered_map *windows = NULL;
35 | }
36 |
37 | ConsoleWindow::ConsoleWindow(Rect r, ConstStr255Param title)
38 | {
39 | GrafPtr port;
40 | win = NewWindow(NULL, &r, "\pos9fetch", true, 0, (WindowPtr)-1, true, 0);
41 |
42 | #if !TARGET_API_MAC_CARBON
43 | port = win;
44 | Rect portRect = port->portRect;
45 | #else
46 | port = GetWindowPort(win);
47 | Rect portRect;
48 | GetPortBounds(port, &portRect);
49 | #endif
50 | #ifdef FOR_PPC
51 | portRect = (Rect){
52 | .top = 0,
53 | .left = 0,
54 | .bottom = 480,
55 | .right = 640,
56 | };
57 | #endif
58 | port->portRect = portRect;
59 |
60 | SetPort(port);
61 | EraseRect(&portRect);
62 |
63 | if (!windows)
64 | windows = new std::unordered_map();
65 | (*windows)[win] = this;
66 |
67 | Init(port, portRect);
68 | }
69 |
70 | ConsoleWindow::~ConsoleWindow()
71 | {
72 | windows->erase(win);
73 | DisposeWindow(win);
74 | }
75 |
76 | void ConsoleWindow::setWindowName(std::string newName)
77 | {
78 | Str255 pname;
79 | #if TARGET_API_MAC_CARBON
80 | // Carbon has the new, sane version.
81 | c2pstrcpy(pname, newName.c_str());
82 | #else
83 | // It is also availble in various glue code libraries and
84 | // in some versions of InterfaceLib, but it's confusing.
85 | // Using the inplace variant, c2pstr, isn't much better than
86 | // doing things by hand:
87 | strncpy((char *)&pname[1], newName.c_str(), 255);
88 | pname[0] = newName.length();
89 | #endif
90 |
91 | SetWTitle(win, pname);
92 | }
93 |
94 | char ConsoleWindow::WaitNextChar()
95 | {
96 | EventRecord event;
97 | WindowPtr eventWin;
98 | ConsoleWindow *realConsole;
99 | #if TARGET_API_MAC_CARBON
100 | Rect *boundsPtr = NULL;
101 | #else
102 | Rect *boundsPtr = &qd.screenBits.bounds;
103 | #endif
104 |
105 | do
106 | {
107 | #if TARGET_API_MAC_CARBON
108 | #define SystemTask()
109 | #endif
110 | SystemTask();
111 | Idle();
112 | while (!GetNextEvent(everyEvent, &event))
113 | {
114 | SystemTask();
115 | Idle();
116 | }
117 |
118 | switch (event.what)
119 | {
120 | case updateEvt:
121 | eventWin = (WindowPtr)event.message;
122 | realConsole = (*windows)[(WindowPtr)event.message];
123 | if (realConsole)
124 | {
125 | Rect updateRect;
126 | BeginUpdate(eventWin);
127 | #if TARGET_API_MAC_CARBON
128 | RgnHandle rgn = NewRgn();
129 | GetPortVisibleRegion(GetWindowPort(eventWin), rgn);
130 | GetRegionBounds(rgn, &updateRect);
131 | DisposeRgn(rgn);
132 | #else
133 | updateRect = (*qd.thePort->visRgn)->rgnBBox; // Life was simple back then.
134 | #endif
135 | realConsole->Draw(updateRect);
136 | EndUpdate(eventWin);
137 | }
138 | break;
139 | case mouseDown:
140 | switch (FindWindow(event.where, &eventWin))
141 | {
142 | case inDrag:
143 | DragWindow(eventWin, event.where, boundsPtr);
144 | break;
145 | case inGrow:
146 | {
147 | long growResult = GrowWindow(eventWin, event.where, boundsPtr);
148 | SizeWindow(eventWin, growResult & 0xFFFF, growResult >> 16, false);
149 | Reshape(Rect{0, 0, (short)(growResult >> 16), (short)(growResult & 0xFFFF)});
150 | }
151 | break;
152 | case inGoAway:
153 | {
154 | if (TrackGoAway(eventWin, event.where))
155 | exit(0);
156 | }
157 | break;
158 | }
159 | break;
160 | }
161 | } while (event.what != keyDown && event.what != autoKey);
162 |
163 | return event.message & charCodeMask;
164 | }
--------------------------------------------------------------------------------
/src/console/ConsoleWindow.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012-2020 Wolfgang Thaller, Davide Bucci
3 |
4 | This file is part of Retro68.
5 |
6 | Retro68 is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Retro68 is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | Under Section 7 of GPL version 3, you are granted additional
17 | permissions described in the GCC Runtime Library Exception, version
18 | 3.1, as published by the Free Software Foundation.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with Retro68. If not, see .
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 |
28 | #include "Console.hpp"
29 |
30 | namespace retro
31 | {
32 | class ConsoleWindow : public Console
33 | {
34 | public:
35 | ConsoleWindow(Rect r, ConstStr255Param title);
36 | ~ConsoleWindow();
37 | void setWindowName(std::string newName);
38 |
39 | private:
40 | WindowPtr win;
41 |
42 | virtual char WaitNextChar();
43 | };
44 | }
--------------------------------------------------------------------------------
/src/console/InitConsole.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2014 Wolfgang Thaller.
3 |
4 | This file is part of Retro68.
5 |
6 | Retro68 is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Retro68 is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | Under Section 7 of GPL version 3, you are granted additional
17 | permissions described in the GCC Runtime Library Exception, version
18 | 3.1, as published by the Free Software Foundation.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with Retro68. If not, see .
22 | */
23 |
24 | #include
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 | #include
34 |
35 | #include "MacUtils.h"
36 | #include "Console.hpp"
37 | #include "ConsoleWindow.hpp"
38 |
39 | namespace retro
40 | {
41 | void InitConsole();
42 | }
43 |
44 | using namespace retro;
45 |
46 | void retro::InitConsole()
47 | {
48 | if (Console::currentInstance)
49 | return;
50 | Console::currentInstance = (Console *)-1;
51 |
52 | #if !TARGET_API_MAC_CARBON
53 | InitGraf(&qd.thePort);
54 | InitFonts();
55 | InitWindows();
56 | InitMenus();
57 |
58 | Rect r = qd.screenBits.bounds;
59 | #else
60 | Rect r = (*GetMainDevice())->gdRect;
61 | #endif
62 |
63 | #ifdef FOR_PPC
64 | r = (Rect){
65 | .top = (r.bottom / 4),
66 | .left = (r.right / 4),
67 | .bottom = (r.bottom / 4) + 480,
68 | .right = (r.bottom / 4) + 640,
69 | };
70 | #endif
71 | {
72 | // give MultiFinder a chance to bring the App to front
73 | // see Technote TB 35 - MultiFinder Miscellanea
74 | // "If your application [...] has the canBackground bit set in the
75 | // size resource, then it should call _EventAvail several times
76 | // (or _WaitNextEvent or _GetNextEvent) before putting up the splash
77 | // screen, or the splash screen will come up behind the frontmost
78 | // layer. If the canBackground bit is set, MultiFinder will not move
79 | // your layer to the front until you call _GetNextEvent,
80 | // _WaitNextEvent, or _EventAvail."
81 |
82 | EventRecord event;
83 | for (int i = 0; i < 5; i++)
84 | EventAvail(everyEvent, &event);
85 | }
86 |
87 | r.top += 40;
88 | Console::currentInstance = new ConsoleWindow(r, "\pos9fetch");
89 | InitCursor();
90 | }
91 |
92 | extern "C" ssize_t _consolewrite(int fd, const void *buf, size_t count)
93 | {
94 | if (!Console::currentInstance)
95 | InitConsole();
96 | if (Console::currentInstance == (Console *)-1)
97 | return 0;
98 |
99 | Console::currentInstance->write((const char *)buf, count);
100 | return count;
101 | }
102 |
103 | extern "C" ssize_t _consoleread(int fd, void *buf, size_t count)
104 | {
105 | if (!Console::currentInstance)
106 | InitConsole();
107 | if (Console::currentInstance == (Console *)-1)
108 | return 0;
109 |
110 | static std::string consoleBuf;
111 | if (consoleBuf.size() == 0)
112 | consoleBuf = Console::currentInstance->ReadLine();
113 |
114 | if (count > consoleBuf.size())
115 | count = consoleBuf.size();
116 | memcpy(buf, consoleBuf.data(), count);
117 | consoleBuf = consoleBuf.substr(count);
118 | return count;
119 | }
--------------------------------------------------------------------------------
/src/console/MacUtils.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2012 Wolfgang Thaller.
3 |
4 | This file is part of Retro68.
5 |
6 | Retro68 is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Retro68 is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | Under Section 7 of GPL version 3, you are granted additional
17 | permissions described in the GCC Runtime Library Exception, version
18 | 3.1, as published by the Free Software Foundation.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with Retro68. If not, see .
22 | */
23 |
24 | #include
25 | #include
26 |
27 | namespace retro
28 | {
29 | class PortSetter
30 | {
31 | GrafPtr save;
32 |
33 | public:
34 | PortSetter(GrafPtr port)
35 | {
36 | ::GetPort(&save);
37 | ::SetPort(port);
38 | }
39 |
40 | ~PortSetter()
41 | {
42 | ::SetPort(save);
43 | }
44 | };
45 | }
--------------------------------------------------------------------------------
/src/detection/68kextras.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | namespace detection
5 | {
6 |
7 | void
8 | fpu()
9 | {
10 | SysEnvRec rec;
11 | SysEnvirons(1, &rec);
12 | if (rec.hasFPU)
13 | {
14 | printf("FPU: Yes");
15 | }
16 | else
17 | {
18 | printf("FPU: No");
19 | }
20 | }
21 |
22 | void color()
23 | {
24 | SysEnvRec rec;
25 | SysEnvirons(1, &rec);
26 | if (rec.hasColorQD)
27 | {
28 | printf("Color: Yes");
29 | }
30 | else
31 | {
32 | printf("Color: No");
33 | }
34 | }
35 |
36 | void keyboard()
37 | {
38 | SysEnvRec rec;
39 | SysEnvirons(1, &rec);
40 | switch (rec.keyBoardType)
41 | {
42 | case 0:
43 | printf("Keyboard: Unknown");
44 | break;
45 | case 1:
46 | printf("Keyboard: Macintosh Keyboard");
47 | break;
48 | case 2:
49 | printf("Keyboard: Macintosh Keyboard (w/ Keypad)");
50 | break;
51 | case 3:
52 | printf("Keyboard: Macintosh Plus Keyboard (w/ Keypad)");
53 | break;
54 | case 4:
55 | printf("Keyboard: Apple Extended Keyboard");
56 | break;
57 | case 5:
58 | printf("Keyboard: Standard ADB Keyboard");
59 | break;
60 | case 6:
61 | printf("Keyboard: Portable ADB Keyboard");
62 | break;
63 | case 7:
64 | printf("Keyboard: Portable ISO Keyboard");
65 | break;
66 | case 8:
67 | printf("Keyboard: Standard ISO ADB");
68 | break;
69 | case 9:
70 | printf("Keyboard: Extended ISO ADB");
71 | break;
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/src/detection/battery.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | namespace detection
5 | {
6 | int battery_count()
7 | {
8 | return BatteryCount();
9 | }
10 |
11 | bool has_battery()
12 | {
13 | return detection::battery_count() >= 1;
14 | }
15 | void battery()
16 | {
17 |
18 | short count = (short)detection::battery_count();
19 |
20 | for (short i = 0; i < count - 1; i++)
21 | {
22 | BatteryInfo info;
23 | GetScaledBatteryInfo(i, &info);
24 | BatteryTimeRec time;
25 | GetBatteryTimes(i, &time);
26 | printf("Battery");
27 | if (count - 1 >= 2)
28 | {
29 | printf(" %d", i);
30 | }
31 | printf(": %f%%", ((float)info.batteryLevel / 255.0f) * 100.0);
32 | if (count - 1 >= 2)
33 | {
34 | printf(", ", i);
35 | }
36 | if (info.flags & batteryCharging == batteryCharging)
37 | {
38 | printf(" (Charging)");
39 | }
40 | if (info.flags & batteryDeadBit == batteryDeadBit)
41 | {
42 | printf(" (Dead)");
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/detection/cpu.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include "functions.hpp"
6 |
7 | #include "xpostcode/CPUDevice.h"
8 | #include
9 | #include
10 |
11 | #include "xpostcode/CPUDevice.h"
12 |
13 | namespace detection
14 | {
15 |
16 | #ifdef FOR_68K
17 | void cpu_68k();
18 | void cpu()
19 | {
20 | cpu_68k();
21 | }
22 | #endif
23 | #ifdef FOR_PPC
24 | void cpu_ppc();
25 | void cpu()
26 | {
27 | cpu_ppc();
28 | }
29 | #endif
30 | void clockSpeed();
31 |
32 | void cpu_68k()
33 | {
34 | int ver = os_version();
35 |
36 | long procType;
37 | if (ver >= 0x605)
38 | {
39 | procType = detection::gestalt(gestaltProcessorType);
40 | }
41 | else
42 | {
43 | SysEnvRec rec;
44 | SysEnvirons(1, &rec);
45 | procType = rec.processor;
46 | }
47 | if (procType != NULL)
48 | {
49 | switch (procType)
50 | {
51 | case gestalt68000:
52 | printf("CPU: 68000");
53 | break;
54 | case gestalt68010:
55 | printf("CPU: 68010");
56 | break;
57 | case gestalt68020:
58 | printf("CPU: 68020");
59 | break;
60 | case gestalt68030:
61 | printf("CPU: 68030");
62 | break;
63 | case gestalt68040:
64 | printf("CPU: 68040");
65 | break;
66 | }
67 |
68 | #ifdef FOR_PPC
69 | int ver = os_version();
70 | if (ver >= 0x605)
71 | {
72 | clockSpeed();
73 | }
74 | #endif
75 | printf(" (ID: %d)", procType);
76 | }
77 | }
78 |
79 | void cpu_ppc()
80 | {
81 | CPUDevice::Initialize();
82 | auto vec = CPUDevice::GetCPUS();
83 | for (int i = 0; i < vec.size(); i++)
84 | {
85 | UInt32 propSize;
86 | auto entry = vec.at(i);
87 |
88 | int cpuNumber = 0;
89 | auto err = RegistryPropertyGetSize(&entry, kCPUIDPropName, &propSize);
90 | if ((err == noErr) && (propSize == sizeof(cpuNumber)))
91 | {
92 | ThrowIfOSErr_AC(RegistryPropertyGet(&entry, kCPUIDPropName, &cpuNumber, &propSize));
93 | }
94 |
95 | uint processorVersion = 0;
96 | err = RegistryPropertyGetSize(&entry, kCPUVersionPropName, &propSize);
97 | if ((err == noErr) && (propSize == sizeof(processorVersion)))
98 | {
99 | ThrowIfOSErr_AC(RegistryPropertyGet(&entry, kCPUVersionPropName, &processorVersion, &propSize));
100 | }
101 | std::string name;
102 |
103 | switch (processorVersion)
104 | {
105 | case 0x00010001:
106 | name = "PowerPC 601 Rev. 0.1";
107 | break;
108 | case 0x00010002:
109 | name = "PowerPC 601 Rev. 0.1";
110 | break;
111 | case 0x00030001:
112 | name = "PowerPC 603 Rev. 0.1";
113 | break;
114 | case 0x00060101:
115 | name = "PowerPC 603e Rev. 1.1";
116 | break;
117 | case 0x00060102:
118 | name = "PowerPC 603e Rev. 1.2";
119 | break;
120 | case 0x00060103:
121 | name = "PowerPC 603e Rev. 1.3";
122 | break;
123 | case 0x00060104:
124 | name = "PowerPC 603e Rev. 1.4";
125 | break;
126 | case 0x00060202:
127 | name = "PowerPC 603e Rev. 2.2";
128 | break;
129 | case 0x00060300:
130 | name = "PowerPC 603e Rev. 3.0";
131 | break;
132 | case 0x00060400:
133 | name = "PowerPC 603e Rev. 4.0";
134 | break;
135 | case 0x00060401:
136 | name = "PowerPC 603e Rev. 4.1";
137 | break;
138 | case 0x00070101:
139 | name = "PowerPC 603ev Rev. 1.1";
140 | break;
141 | case 0x00071201:
142 | name = "PowerPC 603r Rev. 2.1";
143 | break;
144 | case 0x00040103:
145 | name = "PowerPC 604 Rev. 1.3";
146 | break;
147 | case 0x00090204:
148 | name = "PowerPC 604e Rev. 2.4";
149 | break;
150 | case 0x00080100:
151 | name = "PowerPC G3 740/750 Rev. 1.0";
152 | break;
153 | case 0x00080200:
154 | name = "PowerPC G3 740/750 Rev. 2.0";
155 | break;
156 | case 0x00080300:
157 | name = "PowerPC G3 740/750 Rev. 3.0";
158 | break;
159 | case 0x00080301:
160 | name = "PowerPC G3 740/750 Rev. 3.1";
161 | break;
162 | case 0x00082202:
163 | name = "PowerPC G3 750CX Rev. 2.2";
164 | break;
165 | case 0x00082214:
166 | name = "PowerPC G3 750CXe Rev. 2.4";
167 | break;
168 | case 0x00082311:
169 | name = "PowerPC G3 750CXe Rev. 3.1";
170 | break;
171 | case 0x70000100:
172 | case 0x70000101:
173 | case 0x70000102:
174 | case 0x70000103:
175 | case 0x70000104:
176 | case 0x70000105:
177 | case 0x70000106:
178 | case 0x70000107:
179 | case 0x70000108:
180 | case 0x70000109:
181 | case 0x7000010A:
182 | case 0x7000010B:
183 | case 0x7000010C:
184 | case 0x7000010D:
185 | case 0x7000010E:
186 | case 0x7000010F:
187 | name = "PowerPC G3 750FX Rev. 1.x";
188 | break;
189 | case 0x70000200:
190 | name = "PowerPC G3 750FX Rev. 2.0";
191 | break;
192 | case 0x70000201:
193 | name = "PowerPC G3 750FX Rev. 2.1";
194 | break;
195 | case 0x70000202:
196 | name = "PowerPC G3 750FX Rev. 2.2";
197 | break;
198 | case 0x70000203:
199 | name = "PowerPC G3 750FX Rev. 2.3";
200 | break;
201 | case 0x00080202:
202 | name = "PowerPC G3 740(P)/750(P) Rev. 1.1/1.2/2.1";
203 | break;
204 | case 0x00083100:
205 | name = "PowerPC G3 745/755 Rev. 1.0";
206 | break;
207 | case 0x00083101:
208 | name = "PowerPC G3 745/755 Rev. 1.1";
209 | break;
210 | case 0x00083200:
211 | name = "PowerPC G3 745/755 Rev. 2.0";
212 | break;
213 | case 0x00083201:
214 | name = "PowerPC G3 745/755 Rev. 2.1";
215 | break;
216 | case 0x00083202:
217 | name = "PowerPC G3 745/755 Rev. 2.2";
218 | break;
219 | case 0x00083203:
220 | name = "PowerPC G3 745/755 Rev. 2.3";
221 | break;
222 | case 0x00083204:
223 | name = "PowerPC G3 745/755 Rev. 2.4";
224 | break;
225 | case 0x00083205:
226 | name = "PowerPC G3 745/755 Rev. 2.5";
227 | break;
228 | case 0x00083206:
229 | name = "PowerPC G3 745/755 Rev. 2.6";
230 | break;
231 | case 0x00083207:
232 | name = "PowerPC G3 745/755 Rev. 2.7";
233 | break;
234 | case 0x00083208:
235 | name = "PowerPC G3 745/755 Rev. 2.8";
236 | break;
237 | case 0x000c0101:
238 | name = "PowerPC G4 7400 Rev. 1.1";
239 | break;
240 | case 0x000c0200:
241 | name = "PowerPC G4 7400 Rev. 2.0";
242 | break;
243 | case 0x000c0202:
244 | name = "PowerPC G4 7400 Rev. 2.2";
245 | break;
246 | case 0x000c0206:
247 | name = "PowerPC G4 7400 Rev. 2.6";
248 | break;
249 | case 0x000c0207:
250 | name = "PowerPC G4 7400 Rev. 2.7";
251 | break;
252 | case 0x000c0209:
253 | name = "PowerPC G4 7400 Rev. 2.8";
254 | break;
255 | case 0x000c0208:
256 | name = "PowerPC G4 7400 Rev. 2.9";
257 | break;
258 | case 0x800c1101:
259 | name = "PowerPC G4 7410 Rev. 1.1";
260 | break;
261 | case 0x800c1102:
262 | name = "PowerPC G4 7410 Rev. 1.2";
263 | break;
264 | case 0x800c1103:
265 | name = "PowerPC G4 7410 Rev. 1.3";
266 | break;
267 | case 0x800c1104:
268 | name = "PowerPC G4 7410 Rev. 1.4";
269 | break;
270 | case 0x80000100:
271 | name = "PowerPC G4 7450 Rev. 1.0";
272 | break;
273 | case 0x80000101:
274 | name = "PowerPC G4 7450 Rev. 1.1";
275 | break;
276 | case 0x80000102:
277 | name = "PowerPC G4 7450 Rev. 1.2";
278 | break;
279 | case 0x80000200:
280 | name = "PowerPC G4 7450 Rev. 2.0";
281 | break;
282 | case 0x80000201:
283 | name = "PowerPC G4 7441/7450 Rev. 2.1";
284 | break;
285 | case 0x80000203:
286 | name = "PowerPC G4 7441/7451 Rev. 2.3";
287 | break;
288 | case 0x80000202:
289 | name = "PowerPC G4 7441 Rev. 2.2";
290 | break;
291 | case 0x80010201:
292 | name = "PowerPC G4 7445/7455 Rev. 2.1";
293 | break;
294 | case 0x80010302:
295 | name = "PowerPC G4 7445/7455 Rev. 3.2";
296 | break;
297 | case 0x80010303:
298 | name = "PowerPC G4 7445/7455 Rev. 3.3";
299 | break;
300 | case 0x80010304:
301 | name = "PowerPC G4 7445/7455 Rev. 3.4";
302 | break;
303 | case 0x80020100:
304 | name = "PowerPC G4 7447/7457 Rev. 1.0";
305 | break;
306 | case 0x80020101:
307 | name = "PowerPC G4 7447/7457 Rev. 1.1";
308 | break;
309 | case 0x80020102:
310 | name = "PowerPC G4 7447/7457 Rev. 1.2";
311 | break;
312 | case 0x00390202:
313 | name = "PowerPC G5 970 Rev. 2.2";
314 | break;
315 | case 0x003c0300:
316 | name = "PowerPC G5 970FX Rev. 3.0";
317 | break;
318 | case 0x00200000:
319 | name = "PowerPC 403GA";
320 | break;
321 | case 0x00200100:
322 | name = "PowerPC 403GB";
323 | break;
324 | case 0x00200200:
325 | name = "PowerPC 403GC";
326 | break;
327 | case 0x00201400:
328 | name = "PowerPC 403GCX";
329 | break;
330 | case 0x40110000:
331 | name = "PowerPC 405GP";
332 | break;
333 | case 0x40110040:
334 | name = "PowerPC 405GP Rev. B";
335 | break;
336 | case 0x40110082:
337 | name = "PowerPC 405GP Rev. C";
338 | break;
339 | case 0x401100C4:
340 | name = "PowerPC 405GP Rev. D";
341 | break;
342 | case 0x40110145:
343 | name = "PowerPC 405GP Rev. E or 405CR Rev. C";
344 | break;
345 | case 0x40110041:
346 | name = "PowerPC 405CR Rev. A";
347 | break;
348 | case 0x401100C5:
349 | name = "PowerPC 405CR Rev. B";
350 | break;
351 | case 0x51210950:
352 | name = "PowerPC 405EP Rev. A or Rev. B";
353 | break;
354 | case 0x50910951:
355 | name = "PowerPC 405GPR Rev. B";
356 | break;
357 | case 0x41511460:
358 | name = "PowerPC 405EZ Rev. A";
359 | break;
360 | case 0x12911471:
361 | name = "PowerPC 405EXR2 Rev. A";
362 | break;
363 | case 0x12911477:
364 | name = "PowerPC 405EX1 Rev. A";
365 | break;
366 | case 0x1291147B:
367 | name = "PowerPC 405EXR1 Rev. C";
368 | break;
369 | case 0x12911479:
370 | name = "PowerPC 405EXR2 Rev. C";
371 | break;
372 | case 0x1291147F:
373 | name = "PowerPC 405EX1 Rev. C";
374 | break;
375 | case 0x1291147D:
376 | name = "PowerPC 405EX2 Rev. C";
377 | break;
378 | case 0x12911472:
379 | name = "PowerPC 405EXR1 Rev. D";
380 | break;
381 | case 0x12911470:
382 | name = "PowerPC 405EXR2 Rev. D";
383 | break;
384 | case 0x12911475:
385 | name = "PowerPC 405EX1 Rev. D";
386 | break;
387 | case 0x12911473:
388 | name = "PowerPC 405EX2 Rev. D";
389 | break;
390 | case 0x40120440:
391 | name = "PowerPC 440GP Rev. B";
392 | break;
393 | case 0x40120481:
394 | name = "PowerPC 440GP Rev. C";
395 | break;
396 | case 0x42221850:
397 | name = "PowerPC 440EP Rev. A";
398 | break;
399 | case 0x422218D3:
400 | name = "PowerPC 440EP Rev. B or 440GR Rev. A";
401 | break;
402 | case 0x422218D4:
403 | name = "PowerPC 440EP Rev. C or 440GR Rev. B";
404 | break;
405 | case 0x216218D0:
406 | name = "PowerPC 440EPX1 Rev. A or 440GRX1 Rev. A";
407 | break;
408 | case 0x216218D4:
409 | name = "PowerPC 440EPX2 Rev. A or 440GRX2 Rev. A";
410 | break;
411 | case 0x51B21850:
412 | name = "PowerPC 440GX Rev. A";
413 | break;
414 | case 0x51B21851:
415 | name = "PowerPC 440GX Rev. B";
416 | break;
417 | case 0x51B21892:
418 | name = "PowerPC 440GX Rev. C";
419 | break;
420 | case 0x51B21894:
421 | name = "PowerPC 440GX Rev. F";
422 | break;
423 | case 0x53221850:
424 | name = "PowerPC 440SP_6 Rev. AB";
425 | break;
426 | case 0x53321850:
427 | name = "PowerPC 440SP Rev. AB";
428 | break;
429 | case 0x53221891:
430 | name = "PowerPC 440SP_6 Rev. C";
431 | break;
432 | case 0x53321891:
433 | name = "PowerPC 440SP Rev. C";
434 | break;
435 | case 0x53421890:
436 | name = "PowerPC 440SPe_6 Rev. A";
437 | break;
438 | case 0x53521890:
439 | name = "PowerPC 440SPe Rev. A";
440 | break;
441 | case 0x53421891:
442 | name = "PowerPC 440SPe_6 Rev. B";
443 | break;
444 | case 0x53521891:
445 | name = "PowerPC 440SPe Rev. B";
446 | break;
447 | case 0x130218A2:
448 | name = "PowerPC 460EX_SE Rev. A";
449 | break;
450 | case 0x130218A3:
451 | name = "PowerPC 460EX Rev. A";
452 | break;
453 | case 0x130218A4:
454 | name = "PowerPC 460EX Rev. B";
455 | break;
456 | case 0x130218A0:
457 | name = "PowerPC 460GT_SE Rev. A";
458 | break;
459 | case 0x130218A1:
460 | name = "PowerPC 460GT Rev. A";
461 | break;
462 | case 0x130218A5:
463 | name = "PowerPC 460GT Rev. B";
464 | break;
465 | case 0x13541800:
466 | name = "PowerPC 460SX Rev. A";
467 | break;
468 | case 0x13541801:
469 | name = "PowerPC 460SX Rev. A_V1";
470 | break;
471 | case 0x13541802:
472 | name = "PowerPC 460GX Rev. A";
473 | break;
474 | case 0x13541803:
475 | name = "PowerPC 460GX Rev. A_V1";
476 | break;
477 | case 0x12C41C80:
478 | name = "PowerPC APM821XX Rev. A";
479 | break;
480 | case 0x00010000:
481 | name = "PowerPC 601";
482 | break;
483 | case 0x00050000:
484 | name = "PowerPC 602";
485 | break;
486 | case 0x00030000:
487 | name = "PowerPC 603";
488 | break;
489 | case 0x00060000:
490 | name = "PowerPC 603e";
491 | break;
492 | case 0x00070000:
493 | name = "PowerPC 603ev";
494 | break;
495 | case 0x00071000:
496 | name = "PowerPC 603r";
497 | break;
498 | case 0x00040000:
499 | name = "PowerPC 604";
500 | break;
501 | case 0x00090000:
502 | name = "PowerPC 604e";
503 | break;
504 | case 0x000A0000:
505 | name = "PowerPC 604r";
506 | break;
507 | case 0x00140000:
508 | name = "PowerPC 620";
509 | break;
510 | case 0x00080000:
511 | name = "PowerPC 740/750";
512 | break;
513 | case 0x10080000:
514 | name = "PowerPC 740P/750P";
515 | break;
516 | case 0x000C0000:
517 | name = "PowerPC 7400";
518 | break;
519 | case 0x800C0000:
520 | name = "PowerPC 7410";
521 | break;
522 | case 0x80000000:
523 | name = "PowerPC 7450";
524 | break;
525 | case 0x80200000:
526 | name = "PowerPC 85xx";
527 | break;
528 | case 0x80210000:
529 | name = "PowerPC 85xx Rev. 1.0";
530 | break;
531 | case 0x80220000:
532 | name = "PowerPC 85xx Rev. 1.0";
533 | break;
534 | case 0x80040000:
535 | name = "PowerPC 86xx";
536 | break;
537 | case 0x7ff21912:
538 | name = "PowerPC VIRTEX5";
539 | break;
540 | case 0x00500000:
541 | name = "PowerPC 821/832/850/860";
542 | break;
543 | case 0x00810100:
544 | name = "PowerPC 8240/8240/8260";
545 | break;
546 | case 0x00810101:
547 | name = "PowerPC 8260_HIP3";
548 | break;
549 | case 0x80811014:
550 | name = "PowerPC 8260_HIP4";
551 | break;
552 | case 0x80822011:
553 | name = "PowerPC 5200/8260_HIP7";
554 | break;
555 | case 0x80822013:
556 | name = "PowerPC 8260_HIP7R1";
557 | break;
558 | case 0x80822014:
559 | name = "PowerPC 5200B/8260_HIP7RA";
560 | break;
561 |
562 | default:
563 | name = "Unknown";
564 | break;
565 | }
566 |
567 | printf("CPU: %s", name.c_str());
568 |
569 | clockSpeed();
570 |
571 | printf(" (ID: %0X)", processorVersion);
572 | }
573 | }
574 |
575 | void clockSpeed()
576 | {
577 | float speed = (float)detection::gestalt(gestaltProcClkSpeed);
578 | if (speed != NULL)
579 | {
580 | if (speed < 1024.0)
581 | {
582 | printf(" %0.2fHz", speed);
583 | }
584 | else if (speed < 1048576.0)
585 | {
586 | printf(" %0.2fKHz", speed / 1024.0);
587 | }
588 | else if (speed < 1073741824.0)
589 | {
590 | printf(" %0.2fMHz", speed / 1048576.0);
591 | }
592 | else if (speed < 1099511627776.0)
593 | {
594 | printf(" %0.2fGHz", speed / 1073741824.0);
595 | }
596 | else if (speed < 1125899906842624.0)
597 | {
598 | printf(" %0.2fTHz", speed / 1099511627776.0);
599 | }
600 | else
601 | {
602 | printf(" %0.2fPHz", speed / 1125899906842624.0);
603 | }
604 | printf(" (%0.2f)", speed);
605 | }
606 | }
607 | void model()
608 | {
609 | int ver = os_version();
610 |
611 | long sys;
612 | if (ver >= 0x605)
613 | {
614 | sys = detection::gestalt(gestaltMachineType);
615 | }
616 | else
617 | {
618 | SysEnvRec rec;
619 | SysEnvirons(1, &rec);
620 | sys = rec.machineType;
621 | // The result we get near perfectly maps to the modern one, with some exceptions.
622 | if (sys == 1)
623 | {
624 | sys = -1;
625 | }
626 | else if (sys == 2)
627 | {
628 | sys = 2;
629 | }
630 | else
631 | {
632 | sys -= 2;
633 | }
634 | }
635 | if (sys != NULL)
636 | {
637 | // We're supposed to be able to use GetIndString. This does not work, presumably because they stopped updating the index, but they did give us all the numbers in the last header file.
638 | const char *name = NULL;
639 | unsigned char *name2 = NULL;
640 | switch (sys)
641 | {
642 | case 0:
643 | name = "Macintosh 128k";
644 | break;
645 | case 1:
646 | name = "Macintosh Classic";
647 | break;
648 | case 2:
649 | name = "Macintosh XL";
650 | break;
651 | case 3:
652 | name = "Macintosh 512K";
653 | break;
654 |
655 | case 4:
656 | name = "Macintosh Plus";
657 | break;
658 | case 5:
659 | name = "Macintosh SE";
660 | break;
661 | case 6:
662 | name = "Macintosh II";
663 | break;
664 | case 7:
665 | name = "Macintosh IIx";
666 | break;
667 |
668 | case 8:
669 | name = "Macintosh IIcx";
670 | break;
671 | case 9:
672 | name = "Macintosh SE030";
673 | break;
674 | case 10:
675 | name = "Macintosh Portable";
676 | break;
677 | case 11:
678 | name = "Macintosh IIci";
679 | break;
680 |
681 | case 12:
682 | name = "Power Macintosh 8100/120";
683 | break;
684 | case 13:
685 | name = "Macintosh IIfx";
686 | break;
687 | case 17:
688 | name = "Macintosh Classic";
689 | break;
690 | case 18:
691 | name = "Macintosh IIsi";
692 | break;
693 |
694 | case 19:
695 | name = "Macintosh LC";
696 | break;
697 | case 20:
698 | name = "Macintosh Quadra 900";
699 | break;
700 | case 21:
701 | name = "PowerBook 170";
702 | break;
703 | case 22:
704 | name = "Macintosh Quadra 700";
705 | break;
706 |
707 | case 23:
708 | name = "Classic II";
709 | break;
710 | case 24:
711 | name = "PowerBook 100";
712 | break;
713 | case 25:
714 | name = "PowerBook 140";
715 | break;
716 | case 26:
717 | name = "Macintosh Quadra950";
718 | break;
719 |
720 | case 27:
721 | name = "Macintosh LCIII or Performa 450";
722 | break;
723 |
724 | case 29:
725 | name = "PowerBook Duo 210";
726 | break;
727 | case 30:
728 | name = "Macintosh Centris650";
729 | break;
730 |
731 | case 32:
732 | name = "PowerBook Duo 230";
733 | break;
734 | case 33:
735 | name = "PowerBook 180";
736 | break;
737 | case 34:
738 | name = "PowerBook 160";
739 | break;
740 | case 35:
741 | name = "Macintosh Quadra800";
742 | break;
743 |
744 | case 36:
745 | name = "Macintosh Quadra650";
746 | break;
747 | case 37:
748 | name = "Macintosh LCII";
749 | break;
750 | case 38:
751 | name = "PowerBook Duo 250";
752 | break;
753 | case 39:
754 | name = "Apple Macintosh WGS 9150/80";
755 | break;
756 |
757 | case 40:
758 | name = "Power Macintosh 8100/110 or Apple Macintosh WGS 8110";
759 | break;
760 | case 41:
761 | name = "Power Macintosh 52x0 or 5300";
762 | break;
763 | case 42:
764 | name = "Power Macintosh 6200 or Performa 6300";
765 | break;
766 | case 44:
767 | name = "Macintosh IIvi";
768 | break;
769 | case 45:
770 | name = "Macintosh IIvm or Performa 600";
771 | break;
772 | case 47:
773 | name = "Power Macintosh 7100/80";
774 | break;
775 | case 48:
776 | name = "Macintosh IIvx";
777 | break;
778 |
779 | case 49:
780 | name = "Macintosh Color Classic or Performa 250";
781 | break;
782 | case 50:
783 | name = "PowerBook 165c";
784 | break;
785 | case 52:
786 | name = "Macintosh Centris610";
787 | break;
788 |
789 | case 53:
790 | name = "Macintosh Quadra610";
791 | break;
792 | case 54:
793 | name = "PowerBook 145";
794 | break;
795 | case 55:
796 | name = "Power Macintosh 8100/100";
797 | break;
798 | case 56:
799 | name = "Macintosh LC520";
800 | break;
801 |
802 | case 57:
803 | name = "Apple Macintosh WGS 9150/120";
804 | break;
805 | case 58:
806 | name = "Power Macintosh 6400 or Performa 6400 or Performa 6360";
807 | break;
808 |
809 | case 60:
810 | name = "Macintosh Centris660AV or Quadra660AV";
811 | break;
812 | case 62:
813 | name = "Performa 46x";
814 | break;
815 | case 65:
816 | name = "Power Macintosh 8100/80 or Apple Macintosh WGS 8150/80";
817 | break;
818 | case 67:
819 | name = "Power Macintosh 9x00";
820 | break;
821 | case 68:
822 | name = "Power Macintosh 7x00 or Apple Macintosh WGS 8550";
823 | break;
824 | case 69:
825 | name = "Power Macintosh 8x00";
826 | break;
827 | case 71:
828 | name = "PowerBook 180c";
829 | break;
830 | case 72:
831 | name = "PowerBook 520 or 520c or 540 or 540c";
832 | break;
833 | case 74:
834 | name = "Power Macintosh 5400";
835 | break;
836 | case 75:
837 | name = "Power Macintosh 6100/60 or Apple Macintosh WGS 6150/60";
838 | break;
839 | case 77:
840 | name = "PowerBook Duo 270c";
841 | break;
842 | case 78:
843 | name = "Macintosh Quadra840AV";
844 | break;
845 | case 80:
846 | name = "Performa 550";
847 | break;
848 | case 84:
849 | name = "PowerBook 165";
850 | break;
851 |
852 | case 85:
853 | name = "PowerBook 190";
854 | break;
855 | case 88:
856 | name = "Macintosh TV";
857 | break;
858 | case 89:
859 | name = "Macintosh LC475 or Performa 47x";
860 | break;
861 |
862 | case 92:
863 | name = "Macintosh LC575";
864 | break;
865 | case 94:
866 | name = "Macintosh Quadra605";
867 | break;
868 | case 98:
869 | name = "Macintosh Quadra630";
870 | break;
871 | case 99:
872 | name = "Macintosh LC580 or Performa 580";
873 | break;
874 | case 100:
875 | name = "Power Macintosh 6100/66 or Apple Macintosh WGS 6150/66";
876 | break;
877 | case 102:
878 | name = "PowerBook Duo 280";
879 | break;
880 | case 103:
881 | name = "PowerBook Duo 280c";
882 | break;
883 | case 104:
884 | name = "Power Macintosh LC475 or Power Macintosh Performa 47x";
885 | break;
886 | case 105:
887 | name = "Power Macintosh LC575 or Power Macintosh Performa 57x";
888 | break;
889 | case 106:
890 | name = "Power Macintosh Quadra 630 or Power Macintosh LC630 or Performa 63x";
891 | break;
892 | case 108:
893 | name = "Power Macintosh 7200";
894 | break;
895 | case 109:
896 | name = "Power Macintosh 7300";
897 | break;
898 | case 112:
899 | name = "Power Macintosh 7100/66";
900 | break;
901 | case 115:
902 | name = "PowerBook 150";
903 | break;
904 | case 116:
905 | name = "Power Macintosh Quadra 700";
906 | break;
907 | case 117:
908 | name = "Power Macintosh Quadra 900";
909 | break;
910 | case 118:
911 | name = "Power Macintosh Quadra 950";
912 | break;
913 | case 119:
914 | name = "Power Macintosh Centris 610";
915 | break;
916 |
917 | case 120:
918 | name = "Power Macintosh Centris 650";
919 | break;
920 | case 121:
921 | name = "Power Macintosh Quadra 610";
922 | break;
923 | case 122:
924 | name = "Power Macintosh Quadra 650";
925 | break;
926 | case 123:
927 | name = "Power Macintosh Quadra 800";
928 | break;
929 |
930 | case 124:
931 | name = "PowerBook Duo 2300";
932 | break;
933 | case 126:
934 | name = "PowerBook 500 PPC Upgrade";
935 | break;
936 | case 128:
937 | name = "PowerBook 5300";
938 | break;
939 | case 310:
940 | name = "PowerBook 1400";
941 | break;
942 | case 306:
943 | name = "PowerBook 3400";
944 | break;
945 | case 307:
946 | name = "PowerBook 2400";
947 | break;
948 | case 312:
949 | name = "PowerBook G3 Series";
950 | break;
951 | case 313:
952 | name = "PowerBook G3";
953 | break;
954 | case 314:
955 | name = "PowerBook G3 Series 2";
956 | break;
957 | case 406:
958 | name = "New World";
959 | break;
960 | case 510:
961 | name = "Power Macintosh G3";
962 | break;
963 | case 512:
964 | name = "Power Macintosh 5500 or Macintosh 20th Anniversary";
965 | break;
966 | case 513:
967 | name = "Power Macintosh 6500";
968 | break;
969 | case 514:
970 | name = "Power Macintosh 4400/160";
971 | break;
972 | case 515:
973 | name = "Power Macintosh 4400";
974 | break;
975 | default:
976 | GetIndString(name2, -16395, sys);
977 | break;
978 | }
979 | if (name != NULL)
980 | {
981 | printf("Model: %s (ID: %0.2f)", name, sys);
982 | }
983 | else
984 | {
985 | printf("Model: %s (ID: %0.2f)", name2, sys);
986 | }
987 | }
988 | return;
989 | }
990 | }
991 |
--------------------------------------------------------------------------------
/src/detection/disk.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "functions.hpp"
7 |
8 | #define _FSDispatch 0xA060
9 |
10 | namespace detection
11 | {
12 | #ifdef FOR_PPC
13 | pascal OSErr __PBXGetVolInfoSync(XVolumeParamPtr paramBlock)
14 | {
15 | enum
16 | {
17 | kXGetVolInfoSelector = 0x0012, /* Selector for XGetVolInfo */
18 |
19 | uppFSDispatchProcInfo = kRegisterBased | REGISTER_RESULT_LOCATION(kRegisterD0) | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long))) /* trap word */
20 | | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(sizeof(long))) /* selector */
21 | | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr)))
22 | };
23 |
24 | return (CallOSTrapUniversalProc(NGetTrapAddress(_FSDispatch, OSTrap),
25 | uppFSDispatchProcInfo,
26 | _FSDispatch,
27 | kXGetVolInfoSelector,
28 | paramBlock));
29 | }
30 | OSErr HGetVInfo(short volReference,
31 | StringPtr volName,
32 | short *vRefNum,
33 | unsigned long *freeBytes,
34 | unsigned long *totalBytes)
35 | {
36 | HParamBlockRec pb;
37 | unsigned long allocationBlockSize;
38 | unsigned short numAllocationBlocks;
39 | unsigned short numFreeBlocks;
40 | VCB *theVCB;
41 | Boolean vcbFound;
42 | OSErr result;
43 |
44 | pb.volumeParam.ioVRefNum = volReference;
45 | pb.volumeParam.ioNamePtr = volName;
46 | pb.volumeParam.ioVolIndex = 0;
47 | result = PBHGetVInfoSync(&pb);
48 |
49 | if (result == noErr)
50 | {
51 |
52 | *vRefNum = pb.volumeParam.ioVRefNum;
53 | allocationBlockSize = (unsigned long)pb.volumeParam.ioVAlBlkSiz;
54 |
55 | vcbFound = false;
56 | theVCB = (VCB *)(GetVCBQHdr()->qHead);
57 | while ((theVCB != NULL) && !vcbFound)
58 | {
59 |
60 | if (theVCB->vcbSigWord == 0x4244)
61 | {
62 | if (theVCB->vcbVRefNum == *vRefNum)
63 | {
64 | vcbFound = true;
65 | }
66 | }
67 |
68 | if (!vcbFound)
69 | {
70 | theVCB = (VCB *)(theVCB->qLink);
71 | }
72 | }
73 |
74 | if (theVCB != NULL)
75 | {
76 |
77 | numAllocationBlocks = (unsigned short)theVCB->vcbNmAlBlks;
78 | numFreeBlocks = (unsigned short)theVCB->vcbFreeBks;
79 | }
80 | else
81 | {
82 |
83 | numAllocationBlocks = (unsigned short)pb.volumeParam.ioVNmAlBlks;
84 | numFreeBlocks = (unsigned short)pb.volumeParam.ioVFrBlk;
85 | }
86 |
87 | *freeBytes = numFreeBlocks * allocationBlockSize;
88 | *totalBytes = numAllocationBlocks * allocationBlockSize;
89 | }
90 |
91 | return (result);
92 | }
93 | OSErr XGetVInfo(short volReference,
94 | StringPtr volName,
95 | short *vRefNum,
96 | UnsignedWide *freeBytes,
97 | UnsignedWide *totalBytes)
98 | {
99 | OSErr result;
100 | long response;
101 | XVolumeParam pb;
102 |
103 | if ((Gestalt(gestaltFSAttr, &response) == noErr) && ((response & (1L << gestaltFSSupports2TBVols)) != 0))
104 | {
105 |
106 | pb.ioVRefNum = volReference;
107 | pb.ioNamePtr = volName;
108 | pb.ioXVersion = 0;
109 | pb.ioVolIndex = 0;
110 | result = __PBXGetVolInfoSync(&pb);
111 | if (result == noErr)
112 | {
113 |
114 | *vRefNum = pb.ioVRefNum;
115 |
116 | *totalBytes = (UnsignedWide)pb.ioVTotalBytes;
117 | *freeBytes = (UnsignedWide)pb.ioVFreeBytes;
118 | }
119 | }
120 | else
121 | {
122 |
123 | result = HGetVInfo(volReference, volName, vRefNum, &freeBytes->lo, &totalBytes->lo);
124 | if (result == noErr)
125 | {
126 |
127 | totalBytes->hi = 0;
128 | freeBytes->hi = 0;
129 | }
130 | }
131 | return (result);
132 | }
133 | #endif
134 | std::vector driveNumbers;
135 | std::vector drive_numbers()
136 | {
137 | return driveNumbers;
138 | };
139 | short disk_num()
140 | {
141 |
142 | OSErr err = 0;
143 |
144 | for (short i = 3; i < 31; i++)
145 | {
146 | unsigned char *volName;
147 | short vRefNum;
148 | long freeBytes;
149 | err = GetVInfo(i, volName, &vRefNum, &freeBytes);
150 | if (err == 0)
151 | {
152 | driveNumbers.push_back(i);
153 | }
154 | }
155 |
156 | return driveNumbers.size();
157 | }
158 |
159 | OSErr get_name(short i, std::string *res, HVolumeParam *io)
160 | {
161 | OSErr err;
162 | unsigned char *volName;
163 | short vRefNum;
164 | long freeBytes;
165 |
166 | err = GetVInfo(i, volName, &vRefNum, &freeBytes);
167 | if (err != 0)
168 | {
169 | return err;
170 | }
171 |
172 | HParamBlockRec sts = {
173 | .volumeParam = {
174 | .ioCompletion = NULL,
175 | .ioVolIndex = vRefNum,
176 | }};
177 | err = PBHGetVInfo(&sts, false);
178 | if (err != 0)
179 | {
180 | return err;
181 | }
182 | *io = sts.volumeParam;
183 |
184 | auto n = volName;
185 | auto len = n[0];
186 | auto str = std::string();
187 | for (int j = 1; j < len + 1; j++)
188 | {
189 | str += n[j];
190 | };
191 | *res = str;
192 | return 0;
193 | }
194 |
195 | std::function disk(int listNum, short i)
196 | {
197 | return [listNum, i]
198 | {
199 | OSErr err;
200 | unsigned char *volName;
201 | short vRefNum;
202 | long freeBytes;
203 |
204 | err = GetVInfo(i, volName, &vRefNum, &freeBytes);
205 | if (err != 0)
206 | {
207 | printf("Error getting disk %d's name: %d", i, err);
208 | return;
209 | }
210 |
211 | HParamBlockRec sts = {
212 | .volumeParam = {
213 | .ioCompletion = NULL,
214 | .ioVolIndex = listNum,
215 | }};
216 | err = PBHGetVInfo(&sts, false);
217 | if (err != 0)
218 | {
219 | return;
220 | }
221 | auto io = sts.volumeParam;
222 |
223 | auto n = volName;
224 | auto len = n[0];
225 | auto str = std::string();
226 | for (int j = 1; j < len + 1; j++)
227 | {
228 | str += n[j];
229 | };
230 |
231 | float allBlocks = ((float)(unsigned short)io.ioVNmAlBlks * (float)(unsigned long)io.ioVAlBlkSiz);
232 | float freeBlocks = (float)(unsigned long)freeBytes;
233 | printf("Disk %d: %s, ", listNum, str.c_str());
234 | pprintMemory(allBlocks - freeBlocks);
235 | printf("/");
236 | pprintMemory(allBlocks);
237 | printf(" (");
238 | pprintMemory(freeBlocks);
239 | printf(" free) (ID: %d)", i);
240 | };
241 | }
242 | /*std::function disk_below_91(int listNum, short i)
243 | {
244 | return [listNum, i]
245 | {
246 | HVolumeParam io;
247 | OSErr err;
248 |
249 | float freeBytes = -1.0f;
250 | float totalBytes = -1.0f;
251 | unsigned char *volName_;
252 | volName_ = (unsigned char *)"\0";
253 | short vRefNum;
254 | UnsignedWide freeBytes_;
255 | UnsignedWide totalBytes_;
256 | err = XGetVInfo(i, volName_, &vRefNum, &freeBytes_, &totalBytes_);
257 | freeBytes = (float)freeBytes_.hi + (float)freeBytes_.lo;
258 | totalBytes = (float)totalBytes_.hi + (float)totalBytes_.lo;
259 |
260 | std::string volName;
261 | for (int i = 1; i < volName_[0] + 1; i++)
262 | {
263 | volName += volName_[i];
264 | }
265 | if (err != 0)
266 | {
267 | printf("Error getting disk %d's size: %d", i, err);
268 | return;
269 | }
270 | else
271 | {
272 | printf("Disk %d: %s, ", listNum, volName.c_str());
273 | pprintMemory(totalBytes - freeBytes);
274 | printf("/");
275 | pprintMemory(totalBytes);
276 | printf(" (");
277 | pprintMemory(freeBytes);
278 | printf(" free) (ID: %d)", i);
279 | }
280 | };
281 | }
282 | std::function disk_above_91(int listNum, short i)
283 | {
284 | return [listNum, i]
285 | {
286 | OSErr err;
287 | unsigned char *volName;
288 | short vRefNum;
289 | long freeBytes;
290 |
291 | err = GetVInfo(i, volName, &vRefNum, &freeBytes);
292 | if (err != 0)
293 | {
294 | printf("Error getting disk %d's name: %d", i, err);
295 | return;
296 | }
297 |
298 | HParamBlockRec sts = {
299 | .volumeParam = {
300 | .ioCompletion = NULL,
301 | .ioVolIndex = listNum,
302 | }};
303 | err = PBHGetVInfo(&sts, false);
304 | if (err != 0)
305 | {
306 | return;
307 | }
308 | auto io = sts.volumeParam;
309 |
310 | auto n = volName;
311 | auto len = n[0];
312 | auto str = std::string();
313 | for (int j = 1; j < len + 1; j++)
314 | {
315 | str += n[j];
316 | };
317 |
318 | float allBlocks = ((float)(unsigned short)io.ioVNmAlBlks * (float)(unsigned long)io.ioVAlBlkSiz);
319 | float freeBlocks = (float)(unsigned long)freeBytes;
320 | printf("Disk %d: %s, ", listNum, str.c_str());
321 | pprintMemory(allBlocks - freeBlocks);
322 | printf("/");
323 | pprintMemory(allBlocks);
324 | printf("* (");
325 | pprintMemory(freeBlocks);
326 | printf(" free) (ID: %d)", i);
327 | };
328 | }
329 | std::function disk(int listNum, short i)
330 | {
331 | long sys = detection::gestalt(gestaltSystemVersion);
332 | if (sys == NULL)
333 | {
334 | return [listNum, i] {};
335 | }
336 | if (sys >= 0x910)
337 | {
338 | return disk_above_91(listNum, i);
339 | }
340 | else
341 | {
342 | return disk_below_91(listNum, i);
343 | }
344 | }*/
345 |
346 | void disk_notice()
347 | {
348 | printf("* HFS+ disks not read properly on computers running 9.1+.");
349 | }
350 | }
351 |
352 | /*
353 |
354 | #include
355 | #include
356 | #include
357 | #include
358 | #include
359 | #include "functions.hpp"
360 |
361 | namespace detection
362 | {
363 | OSErr HGetVInfo(short volReference,
364 | StringPtr volName,
365 | short *vRefNum,
366 | unsigned long *freeBytes,
367 | unsigned long *totalBytes)
368 | {
369 | HParamBlockRec pb;
370 | unsigned long allocationBlockSize;
371 | unsigned short numAllocationBlocks;
372 | unsigned short numFreeBlocks;
373 | VCB *theVCB;
374 | Boolean vcbFound;
375 | OSErr result;
376 |
377 |
378 | pb.volumeParam.ioVRefNum = volReference;
379 | pb.volumeParam.ioNamePtr = volName;
380 | pb.volumeParam.ioVolIndex = 0;
381 | result = PBHGetVInfoSync(&pb);
382 |
383 | if (result == noErr)
384 | {
385 |
386 |
387 | *vRefNum = pb.volumeParam.ioVRefNum;
388 | allocationBlockSize = (unsigned long)pb.volumeParam.ioVAlBlkSiz;
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 | vcbFound = false;
401 | theVCB = (VCB *)(GetVCBQHdr()->qHead);
402 | while ((theVCB != NULL) && !vcbFound)
403 | {
404 |
405 |
406 | if (theVCB->vcbSigWord == 0x4244)
407 | {
408 | if (theVCB->vcbVRefNum == *vRefNum)
409 | {
410 | vcbFound = true;
411 | }
412 | }
413 |
414 | if (!vcbFound)
415 | {
416 | theVCB = (VCB *)(theVCB->qLink);
417 | }
418 | }
419 |
420 | if (theVCB != NULL)
421 | {
422 |
423 |
424 | numAllocationBlocks = (unsigned short)theVCB->vcbNmAlBlks;
425 | numFreeBlocks = (unsigned short)theVCB->vcbFreeBks;
426 | }
427 | else
428 | {
429 |
430 |
431 | numAllocationBlocks = (unsigned short)pb.volumeParam.ioVNmAlBlks;
432 | numFreeBlocks = (unsigned short)pb.volumeParam.ioVFrBlk;
433 | }
434 |
435 |
436 | *freeBytes = numFreeBlocks * allocationBlockSize;
437 | *totalBytes = numAllocationBlocks * allocationBlockSize;
438 | }
439 |
440 | return (result);
441 | }
442 | OSErr XGetVInfo(short volReference,
443 | StringPtr volName,
444 | short *vRefNum,
445 | UnsignedWide *freeBytes,
446 | UnsignedWide *totalBytes)
447 | {
448 | OSErr result;
449 | long response;
450 | XVolumeParam pb;
451 |
452 |
453 | if ((Gestalt(gestaltFSAttr, &response) == noErr) && ((response & (1L << gestaltFSSupports2TBVols)) != 0))
454 | {
455 |
456 | pb.ioVRefNum = volReference;
457 | pb.ioNamePtr = volName;
458 | pb.ioXVersion = 0;
459 | pb.ioVolIndex = 0;
460 | result = PBXGetVolInfoSync(&pb);
461 | if (result == noErr)
462 | {
463 |
464 |
465 | *vRefNum = pb.ioVRefNum;
466 |
467 |
468 | *totalBytes = (UnsignedWide)pb.ioVTotalBytes;
469 | *freeBytes = (UnsignedWide)pb.ioVFreeBytes;
470 | }
471 | }
472 | else
473 | {
474 |
475 |
476 |
477 | result = HGetVInfo(volReference, volName, vRefNum, &freeBytes->lo, &totalBytes->lo);
478 | if (result == noErr)
479 | {
480 |
481 | totalBytes->hi = 0;
482 | freeBytes->hi = 0;
483 | }
484 | }
485 | return (result);
486 | }
487 | std::vector driveNumbers;
488 | std::vector drive_numbers()
489 | {
490 | return driveNumbers;
491 | };
492 | short disk_num()
493 | {
494 | OSErr err = 0;
495 | for (short i = 3; i < 31; i++)
496 | {
497 | unsigned char *volName;
498 | short vRefNum;
499 | long freeBytes;
500 | err = GetVInfo(i, volName, &vRefNum, &freeBytes);
501 | if (err == 0)
502 | {
503 | driveNumbers.push_back(i);
504 | }
505 | }
506 |
507 | return driveNumbers.size();
508 | }
509 | std::function disk(int listNum, short i)
510 | {
511 | return [listNum, i]
512 | {
513 | OSErr err;
514 | unsigned char *volName;
515 | short vRefNum;
516 | long freeBytesOld;
517 |
518 | err = GetVInfo(i, volName, &vRefNum, &freeBytesOld);
519 | if (err != 0)
520 | {
521 | printf("Error getting disk %d's name: %d", i, err);
522 | return;
523 | }
524 |
525 | HParamBlockRec sts = {
526 | .volumeParam = {
527 | .ioCompletion = NULL,
528 | .ioVolIndex = listNum,
529 | }};
530 | err = PBHGetVInfo(&sts, false);
531 | if (err != 0)
532 | {
533 | return;
534 | }
535 | auto io = sts.volumeParam;
536 |
537 | auto n = volName;
538 | auto len = n[0];
539 | auto str = std::string();
540 | for (int j = 1; j < len + 1; j++)
541 | {
542 | str += n[j];
543 | };
544 |
545 | UnsignedWide freeBytes;
546 | UnsignedWide totalBytes;
547 |
548 | err = XGetVInfo(vRefNum, volName, &vRefNum, &freeBytes, &totalBytes);
549 |
550 | if (err != 0)
551 | {
552 | return;
553 | }
554 | float allBlocks = (float)(totalBytes.lo) + (float)(totalBytes.hi);
555 | float freeBlocks = (float)(freeBytes.lo) + (float)(freeBytes.hi);
556 |
557 | printf("Disk %d: %s, ", listNum, str.c_str());
558 | pprintMemory(allBlocks - freeBlocks);
559 | printf("/");
560 | pprintMemory(allBlocks);
561 | printf(" (");
562 | pprintMemory(freeBlocks);
563 | printf(" free) (ID: %d)", i);
564 | };
565 | }
566 | }
567 | */
--------------------------------------------------------------------------------
/src/detection/functions.cpp:
--------------------------------------------------------------------------------
1 |
2 |
3 | #include
4 | #include
5 | #include "functions.hpp"
6 |
7 | namespace detection
8 | {
9 | std::vector> functions()
10 | {
11 | int ver = os_version();
12 |
13 | auto vec = std::vector>();
14 |
15 | if (detection::name_avaliable())
16 | {
17 | vec.push_back(std::function(detection::name));
18 | vec.push_back(std::function(detection::line));
19 | }
20 |
21 | vec.push_back(std::function(detection::os));
22 | if (ver >= 0x605)
23 | {
24 | vec.push_back(std::function(detection::rom));
25 | }
26 | vec.push_back(std::function(detection::cpu));
27 | vec.push_back(std::function(detection::model));
28 | if (ver >= 0x605)
29 | {
30 | vec.push_back(std::function(detection::memory));
31 | }
32 | else
33 | {
34 |
35 | vec.push_back(std::function(detection::fpu));
36 | vec.push_back(std::function(detection::color));
37 | vec.push_back(std::function(detection::keyboard));
38 | }
39 | // As far as I know there was only one non-PPC laptop and it has a lead-acid battery that nobody even has working, so we'll be lazy and remove it. Feel free to correct me.
40 | #ifdef FOR_PPC
41 | if (detection::has_battery())
42 | {
43 | vec.push_back(std::function(detection::battery));
44 | }
45 | #endif
46 |
47 | #ifdef FOR_PPC
48 | // Disk support.
49 | if (ver < 0x810)
50 | {
51 | short disks = detection::disk_num();
52 | auto numbers = detection::drive_numbers();
53 | for (int i = 0; i < disks; i++)
54 | {
55 | vec.push_back(std::function(detection::disk(i + 1, numbers[i])));
56 | }
57 | }
58 | #endif
59 | return vec;
60 | }
61 | }
--------------------------------------------------------------------------------
/src/detection/functions.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FUNCTIONS
2 | #define FUNCTIONS
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace detection
9 | {
10 | long gestalt(OSType l);
11 | int os_version();
12 | bool has_battery();
13 | bool name_avaliable();
14 | void memory();
15 | void cpu();
16 | void model();
17 | void os();
18 | void rom();
19 | void battery();
20 | void gpu();
21 | void name();
22 | void line();
23 | void pprintMemory(float memSize);
24 | void pprintMemoryMB(float memSize);
25 | void disk_notice();
26 | bool is_utf8(const char *string);
27 |
28 | void fpu();
29 | void color();
30 | void keyboard();
31 |
32 | std::vector drive_numbers();
33 |
34 | short disk_num();
35 | std::function disk(int listNum, short i);
36 |
37 | // void uptime();
38 | std::vector>
39 | functions();
40 | }
41 | #endif
--------------------------------------------------------------------------------
/src/detection/gestalt.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | namespace detection
5 | {
6 | long gestalt(OSType l)
7 | {
8 | long res = NULL;
9 | auto err = Gestalt(l, &res);
10 | if (err != 0)
11 | {
12 | switch (err)
13 | {
14 | case -5500:
15 | printf("_SysEnvirons trap not present");
16 | break;
17 | case -5501:
18 | printf("negative number used in verReqNo");
19 | break;
20 | case -5502:
21 | printf("verReqNo version not handled by this system.");
22 | break;
23 | }
24 | }
25 | return res;
26 | };
27 |
28 | }
--------------------------------------------------------------------------------
/src/detection/gpu.cpp:
--------------------------------------------------------------------------------
1 | #include "functions.hpp"
2 | #include
3 | #include
4 |
5 | extern "C"
6 | {
7 | void gpu_raw()
8 | {
9 | #ifdef FOR_PPC
10 | const GLubyte *vendor = glGetString(GL_VENDOR); // Returns the vendor
11 | const GLubyte *renderer = glGetString(GL_RENDERER); // Returns a hint to the model
12 | printf("%s, %s", vendor, renderer);
13 | #endif
14 | }
15 | }
16 | namespace detection
17 | {
18 | void gpu()
19 | {
20 | gpu_raw();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/detection/memory.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include "functions.hpp"
5 | #include "Processes.h"
6 | namespace detection
7 | {
8 | void memory()
9 | {
10 |
11 | // failed attempt to get accumulated ram usage
12 | /*OSErr err = 0;
13 | ProcessSerialNumber ptr;
14 | unsigned long usedMem;
15 | while (err != -600)
16 | {
17 | err = GetNextProcess(&ptr);
18 |
19 | ProcessInfoRecPtr info;
20 | OSErr err2 = GetProcessInformation(&ptr, info);
21 | if (err2 != 50)
22 | {
23 | usedMem += (info->processSize - (long)info->processLocation) - info->processFreeMem;
24 | }
25 | }*/
26 | auto memsize = detection::gestalt(gestaltLogicalRAMSize);
27 | if (memsize != NULL)
28 | {
29 | printf("Memory: ");
30 | pprintMemory(memsize);
31 | }
32 |
33 | return;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/detection/misc.cpp:
--------------------------------------------------------------------------------
1 | #include "functions.hpp"
2 | namespace detection
3 | {
4 | bool is_utf8(const char *string)
5 | {
6 | if (!string)
7 | return true;
8 |
9 | const unsigned char *bytes = (const unsigned char *)string;
10 | int num;
11 |
12 | while (*bytes != 0x00)
13 | {
14 | if ((*bytes & 0x80) == 0x00)
15 | {
16 | // U+0000 to U+007F
17 | num = 1;
18 | }
19 | else if ((*bytes & 0xE0) == 0xC0)
20 | {
21 | // U+0080 to U+07FF
22 | num = 2;
23 | }
24 | else if ((*bytes & 0xF0) == 0xE0)
25 | {
26 | // U+0800 to U+FFFF
27 | num = 3;
28 | }
29 | else if ((*bytes & 0xF8) == 0xF0)
30 | {
31 | // U+10000 to U+10FFFF
32 | num = 4;
33 | }
34 | else
35 | return false;
36 |
37 | bytes += 1;
38 | for (int i = 1; i < num; ++i)
39 | {
40 | if ((*bytes & 0xC0) != 0x80)
41 | return false;
42 | bytes += 1;
43 | }
44 | }
45 |
46 | return true;
47 | }
48 |
49 | void pprintMemory(float memsize)
50 | {
51 | if (memsize < 1024.0f)
52 | {
53 | printf("%0.2fB", memsize);
54 | }
55 | else if (memsize < 1048576.0f)
56 | {
57 | printf("%0.2fKB", memsize / 1024.0f);
58 | }
59 | else if (memsize < 1073741824.0f)
60 | {
61 | printf("%0.2fMB", memsize / 1048576.0f);
62 | }
63 | else if (memsize < 1099511627776.0f)
64 | {
65 | printf("%0.2fGB", memsize / 1073741824.0f);
66 | }
67 | else if (memsize < 1125899906842624.0f)
68 | {
69 | printf("%0.2fTB", memsize / 1099511627776.0f);
70 | }
71 | else
72 | {
73 | printf("%0.2fPB", memsize / 1125899906842624.0f);
74 | }
75 | }
76 |
77 | void pprintMemoryMB(float memsize)
78 | {
79 | if (memsize < 1000.0f)
80 | {
81 | printf("%0.2fB", memsize);
82 | }
83 | else if (memsize < 1000000.0f)
84 | {
85 | printf("%0.2fKB", memsize / 1000.0f);
86 | }
87 | else if (memsize < 1000000000.0f)
88 | {
89 | printf("%0.2fMB", memsize / 1000000.0f);
90 | }
91 | else if (memsize < 1000000000000.0f)
92 | {
93 | printf("%0.2fGB", memsize / 1000000000.0f);
94 | }
95 | else if (memsize < 1000000000000000.0f)
96 | {
97 | printf("%0.2fTB", memsize / 1000000000000.0f);
98 | }
99 | else if (memsize < 1000000000000000000.0f)
100 | {
101 | printf("%0.2fPB", memsize / 1000000000000000);
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/src/detection/os.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include "functions.hpp"
6 | namespace detection
7 | {
8 | int os_version()
9 | {
10 |
11 | SysEnvRec rec;
12 | SysEnvirons(1, &rec);
13 | return rec.systemVersion;
14 | }
15 | void os()
16 | {
17 | int sys = os_version();
18 | static char buf[100];
19 | std::string version;
20 | const int len = std::snprintf(buf, sizeof(buf), "%lx", sys);
21 | version = std::string(buf, len);
22 | std::string version_final = std::string();
23 |
24 | for (int i = 0; i < version.length(); i++)
25 | {
26 | version_final += version[i];
27 | if (i <= version.length() - 2)
28 | {
29 | version_final += ".";
30 | }
31 | }
32 | printf("OS Version: %s", version_final.c_str());
33 | }
34 | }
--------------------------------------------------------------------------------
/src/detection/rom.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "functions.hpp"
4 |
5 | namespace detection
6 | {
7 | void rom()
8 | {
9 | long sys = detection::gestalt(gestaltROMVersion);
10 | if (sys != NULL)
11 | {
12 | static char buf[100];
13 | std::string version;
14 | const int len = std::snprintf(buf, sizeof(buf), "%lu", sys);
15 | printf("ROM Version: %s", buf);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/detection/user.cpp:
--------------------------------------------------------------------------------
1 | #include "functions.hpp"
2 | #include
3 | #include
4 |
5 | namespace detection
6 | {
7 | int driveAmount = -1;
8 | bool name_avaliable()
9 | {
10 | HParamBlockRec pb = HParamBlockRec{
11 | .objParam = ObjParam{
12 | .ioCompletion = NULL,
13 | .ioVRefNum = 0,
14 | }};
15 | OSErr err = PBHGetLogInInfo(&pb, false);
16 | if (err != 0)
17 | {
18 | return false;
19 | };
20 |
21 | // We might get a false positive, indicitive by the resulting string not being valid name. Double check to make sure it's valid.
22 | auto n = pb.objParam.ioNamePtr;
23 | auto len = n[0];
24 | auto str = std::string();
25 | for (int i = 1; i < len + 1; i++)
26 | {
27 | str += n[i];
28 | };
29 | return is_utf8(str.c_str());
30 | }
31 |
32 | std::string name_str()
33 | {
34 | std::string name;
35 | HParamBlockRec pb = HParamBlockRec{
36 | .objParam = ObjParam{
37 | .ioCompletion = NULL,
38 | .ioVRefNum = 0,
39 | }};
40 | OSErr err = PBHGetLogInInfo(&pb, false);
41 | if (err == 0)
42 | {
43 | auto n = pb.objParam.ioNamePtr;
44 | auto len = n[0];
45 | auto str = std::string();
46 | for (int i = 1; i < len + 1; i++)
47 | {
48 | name += n[i];
49 | };
50 | }
51 |
52 | auto obj = HParamBlockRec{
53 | .objParam = ObjParam{
54 | .ioCompletion = NULL,
55 | .ioNamePtr = pb.objParam.ioNamePtr,
56 | .ioVRefNum = pb.objParam.ioVRefNum,
57 | .ioObjNamePtr = pb.objParam.ioObjNamePtr,
58 | .ioObjID = pb.objParam.ioObjID,
59 | }};
60 | obj.objParam.ioObjType = 4;
61 | err = PBHMapName(&obj, false);
62 | if (err == 0)
63 | {
64 | name += "@";
65 | auto n = obj.objParam.ioObjNamePtr;
66 | auto len = n[0];
67 | auto str = std::string();
68 | for (int i = 1; i < len + 1; i++)
69 | {
70 | name += n[i];
71 | };
72 | }
73 | return name;
74 | }
75 | void line()
76 | {
77 | auto n = name_str();
78 | for (int i = 0; i < n.length(); i++)
79 | {
80 | printf("-");
81 | }
82 | }
83 | void name()
84 | {
85 | printf("%s", name_str().c_str());
86 | }
87 | }
--------------------------------------------------------------------------------
/src/detection/xpostcode/CPUDevice.cpp:
--------------------------------------------------------------------------------
1 | #include "CPUDevice.h"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | CPUDeviceList CPUDevice::gCPUDeviceList;
8 | bool CPUDevice::gHasBeenInitialized = false;
9 | int CPUDevice::gCPUCount = 0;
10 |
11 | void ThrowIfNULL_AC(void *what, char *hit)
12 | {
13 | if (what == NULL)
14 | {
15 | printf("%s was null!\n", hit);
16 | getchar();
17 | exit(1);
18 | return;
19 | }
20 | };
21 | void ThrowIfOSErr_AC(OSErr what)
22 | {
23 | if (what != 0)
24 | {
25 | printf("Error: %d\n", what);
26 | getchar();
27 | exit(1);
28 | return;
29 | }
30 | };
31 | void CPUDevice::Initialize()
32 | {
33 | if (gHasBeenInitialized)
34 | return;
35 |
36 | gHasBeenInitialized = true;
37 |
38 | // We iterate through, and collected all entries with a device type "cpu"
39 |
40 | RegEntryIter cookie;
41 | RegEntryID entry;
42 | Boolean done = false;
43 | RegEntryIterationOp iterOp = kRegIterDescendants;
44 | OSStatus err = RegistryEntryIterateCreate(&cookie);
45 |
46 | while (true)
47 | {
48 | err = RegistryEntryIterate(&cookie, iterOp, &entry, &done);
49 | if (!done && (err == noErr))
50 | {
51 | RegPropertyValueSize propSize;
52 | err = RegistryPropertyGetSize(&entry, kDeviceTypeProperty, &propSize);
53 | if (err == noErr)
54 | {
55 | char *deviceType = NewPtr(propSize + 1);
56 | ThrowIfNULL_AC(deviceType, "deviceType");
57 | ThrowIfOSErr_AC(RegistryPropertyGet(&entry, kDeviceTypeProperty, deviceType, &propSize));
58 | deviceType[propSize] = '\0';
59 | if (!strcmp(deviceType, "cpu"))
60 | {
61 | gCPUDeviceList.push_back(entry);
62 | }
63 | DisposePtr(deviceType);
64 | }
65 | RegistryEntryIDDispose(&entry);
66 | }
67 | else
68 | {
69 | break;
70 | }
71 | iterOp = kRegIterContinue;
72 | }
73 | RegistryEntryIterateDispose(&cookie);
74 | }
75 |
76 | CPUDevice::~CPUDevice()
77 | {
78 | #ifdef __MACH__
79 | #else
80 | RegistryEntryIDDispose(fRegEntryID);
81 | #endif
82 | }
83 |
84 | #define kCPUIDPropName "cpu#"
85 | #define kCPUVersionPropName "cpu-version"
86 |
87 | CPUDevice::CPUDevice(REG_ENTRY_TYPE regEntry)
88 | {
89 |
90 | ThrowIfNULL_AC(regEntry, "regEntry");
91 | RegistryEntryIDCopy(regEntry, &fRegEntryIDStorage);
92 | fRegEntryID = &fRegEntryIDStorage;
93 |
94 | // OFAliases::AliasFor(fRegEntryID, fOpenFirmwareName, fShortOpenFirmwareName);
95 |
96 | RegPropertyValueSize propSize;
97 |
98 | OSErr err;
99 |
100 | fCPUNumber = 0;
101 | err = RegistryPropertyGetSize(fRegEntryID, kCPUIDPropName, &propSize);
102 | if ((err == noErr) && (propSize == sizeof(fCPUNumber)))
103 | {
104 | ThrowIfOSErr_AC(RegistryPropertyGet(regEntry, kCPUIDPropName, &fCPUNumber, &propSize));
105 | }
106 |
107 | fCPUVersion = 0;
108 | err = RegistryPropertyGetSize(fRegEntryID, kCPUVersionPropName, &propSize);
109 | if ((err == noErr) && (propSize == sizeof(fCPUVersion)))
110 | {
111 | ThrowIfOSErr_AC(RegistryPropertyGet(fRegEntryID, kCPUVersionPropName, &fCPUVersion, &propSize));
112 | }
113 |
114 | #if qLogging
115 | gLogFile << "CPU#: " << fCPUNumber << endl_AC;
116 | gLogFile << "OpenFirmwareName: " << fOpenFirmwareName << endl_AC;
117 | gLogFile << "ShortOpenFirmwareName: " << fShortOpenFirmwareName << endl_AC;
118 | gLogFile << "CPUVersion: " << fCPUVersion << endl_AC;
119 | #endif
120 | }
121 |
122 | std::vector CPUDevice::GetCPUS()
123 | {
124 | return gCPUDeviceList;
125 | }
126 |
--------------------------------------------------------------------------------
/src/detection/xpostcode/CPUDevice.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | CPUDevice
4 | =========
5 |
6 | The function of this class is to maintain a list of all the name registry
7 | entries that are CPUs.
8 |
9 | */
10 |
11 | #ifndef __CPUDEVICE_H__
12 | #define __CPUDEVICE_H__
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | #define kCPUIDPropName "cpu#"
19 | #define kCPUVersionPropName "cpu-version"
20 | #define kDeviceTypeProperty "device_type"
21 |
22 | typedef RegEntryID *REG_ENTRY_TYPE;
23 | class CPUDevice;
24 |
25 | typedef std::vector CPUDeviceList;
26 |
27 | void ThrowIfNULL_AC(void *what, char *hit);
28 | void ThrowIfOSErr_AC(OSErr what);
29 | class CPUDevice
30 | {
31 |
32 | public:
33 | static void Initialize();
34 |
35 | static std::vector GetCPUS();
36 |
37 | static int getCPUCount() { return gCPUCount; }
38 |
39 | ~CPUDevice();
40 |
41 | RegEntryID fRegEntryIDStorage;
42 | REG_ENTRY_TYPE fRegEntryID;
43 | char fOpenFirmwareName[256];
44 | char fShortOpenFirmwareName[256];
45 | UInt32 fCPUNumber;
46 | UInt32 fCPUVersion;
47 |
48 | CPUDevice(REG_ENTRY_TYPE regEntry);
49 |
50 | private:
51 | static CPUDeviceList gCPUDeviceList;
52 | static int gCPUCount;
53 | static bool gHasBeenInitialized;
54 | };
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/src/logo.hpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #pragma once
5 |
6 | static std::vector apple_logo = {" 'c. ",
7 | " ,xNMM. ",
8 | " .OMMMMo ",
9 | " OMMM0, ",
10 | " .;loddo:' loolloddol;. ",
11 | " cKMMMMMMMMMMNWMMMMMMMMMM0: ",
12 | " .KMMMMMMMMMMMMMMMMMMMMMMMWd. ",
13 | " XMMMMMMMMMMMMMMMMMMMMMMMX. ",
14 | ";MMMMMMMMMMMMMMMMMMMMMMMM: ",
15 | ":MMMMMMMMMMMMMMMMMMMMMMMM: ",
16 | ".MMMMMMMMMMMMMMMMMMMMMMMMX. ",
17 | " kMMMMMMMMMMMMMMMMMMMMMMMMWd. ",
18 | " .XMMMMMMMMMMMMMMMMMMMMMMMMMMk ",
19 | " .XMMMMMMMMMMMMMMMMMMMMMMMMK. ",
20 | " kMMMMMMMMMMMMMMMMMMMMMMd ",
21 | " ;KMMMMMMMWXXWMMMMMMMk. ",
22 | " .cooc,. .,coo:. "};
23 |
--------------------------------------------------------------------------------
/src/os9fetch.cpp:
--------------------------------------------------------------------------------
1 | #include "stdio.h"
2 | #include
3 | #include "logo.hpp"
4 |
5 | #include "detection/functions.hpp"
6 | #include "console/Console.hpp"
7 | #include "console/ConsoleWindow.hpp"
8 |
9 | void main_below_4();
10 | void main_above_4();
11 |
12 | int main()
13 | {
14 | retro::InitConsole();
15 |
16 | auto functions = detection::functions();
17 | std::vector buf = std::vector();
18 |
19 | for (int i = 0; i < apple_logo.size(); i++)
20 | {
21 | auto logo = apple_logo[i].c_str();
22 | printf("%s ", logo);
23 | if (i < functions.size())
24 | {
25 | functions[i]();
26 | }
27 | printf("\n");
28 | }
29 |
30 | retro::Console::currentInstance->ReadLine();
31 | return 0;
32 | }
33 |
34 | void main_below_4()
35 | {
36 | retro::InitConsole();
37 |
38 | for (int i = 0; i < apple_logo.size(); i++)
39 | {
40 | auto logo = apple_logo[i];
41 |
42 | retro::Console::currentInstance->write(logo.c_str(), logo.size());
43 | retro::Console::currentInstance->write("\n", 1);
44 | }
45 |
46 | retro::Console::currentInstance->ReadLine();
47 | }
48 |
49 | void main_above_4()
50 | {
51 | retro::InitConsole();
52 |
53 | auto functions = detection::functions();
54 | std::vector buf = std::vector();
55 |
56 | for (int i = 0; i < apple_logo.size(); i++)
57 | {
58 | auto logo = apple_logo[i].c_str();
59 | printf("%s ", logo);
60 | if (i < functions.size())
61 | {
62 | functions[i]();
63 | }
64 | printf("\n");
65 | }
66 |
67 | retro::Console::currentInstance->ReadLine();
68 | }
--------------------------------------------------------------------------------