Skip to content

Add iPhone OS 3 Support - #86

Open
TimofeyLednev wants to merge 98 commits into
AdrienRL1:mainfrom
TimofeyLednev:iOS3iThink
Open

Add iPhone OS 3 Support#86
TimofeyLednev wants to merge 98 commits into
AdrienRL1:mainfrom
TimofeyLednev:iOS3iThink

Conversation

@TimofeyLednev

@TimofeyLednev TimofeyLednev commented Jun 12, 2026

Copy link
Copy Markdown

Added iOS 3 support + a method for launching applications for a specific iOS via a .sh script, added Russian language support, added second method for installing apps., to make this iOS 3 port, Claude Opus 4.8 and Fable 5 were used.

web-flow and others added 30 commits June 3, 2026 16:31
…s+GCD shims)

- compat/AppDropCompat.h: prefix header backfilling iOS6/7 SDK decls missing
  from the iOS 5.1 SDK (NS_ENUM/NS_OPTIONS, subscripting, NSText* renames,
  @YES/@no boxing, NSUUID/firstObject/base64/string-drawing decls).
- compat/AppDropRuntime.m + AppDropJSON.m: +load/runtime backfill of NSUUID,
  NSJSONSerialization (cJSON), NSData base64, NSString sizing/drawing.
- compat/shim: self-contained ARC runtime, blocks runtime (libclosure) and a
  pthread/CFRunLoop libdispatch (GCD) so the binary needs none of these from
  the OS (they don't exist on iOS 3). No-ops/native pass-through on iOS 5+.
- compat/mbed_platform_compat.c: mbedTLS platform_util replacements avoiding
  clock_gettime/CLOCK_MONOTONIC (absent on iOS 3).
- build-ios3.sh: one-command Linux cross-build -> armv6 .ipa + Cydia .deb,
  with a guard that fails if any ARC/blocks/GCD symbol leaks as a dylib import.
- ci-ios3.yml.txt: GitHub Actions workflow (paste into .github/workflows).
- InstallManager.m: message-syntax for -timeIntervalSince1970 (behavior-identical).

Original Theos iOS5+ build path untouched.
Brings Themes/dark mode, Favorites & folders, custom home layout,
Modded section, and app sharing from AdrienRL1/AppDrop (up to 183b940).
Clean merge — iOS3 backport lives isolated under ios3/, so app-source
updates apply without conflicts. MRC conversion to follow on this fresh base.
…work

- AppDropCompat.h: declare UIViewController autorotation selectors,
  UIView/UISwitch -tintColor, and UITableViewHeaderFooterView (all
  iOS 6/7 APIs the v3.0 merge introduced; runtime-guarded in code).
- build-ios3.sh: link -framework CFNetwork (HTTPSClient proxy detection).
- ARC build now compiles all 42 .m clean and links a self-contained
  armv6 binary (IPA + deb), leak gate passes.
Replaces the ARC runtime shim (libarclite stub + objc_retain/release/storeStrong
re-implementations) with native manual reference counting. On real iOS 3.x/4.x
hardware libobjc has no ARC entry points, so the shim was fragile and crash-prone;
MRC compiles retain/release as ordinary objc_msgSend, which the iOS 3 runtime has.

- All 42 .m sources now build under -fno-objc-arc. Clang auto-synthesizes correct
  retaining setters for strong/copy/assign properties, so no ownership edits were
  needed beyond weak references.
- weak references (unsupported pre-iOS5 runtime): 24 __weak locals + 2 weak
  properties -> AD_WEAK (__unsafe_unretained, i.e. non-zeroing weak). Matches the
  old shim's objc_storeWeak behaviour but is explicit and links cleanly.
- build-ios3.sh: compile app under MRC; drop libarclite stub + the clang
  driver-injection retry hack; remove arc_shim.m from the link. blocks + GCD
  shims stay (iOS 3 lacks those regardless of ARC/MRC).
- AppDropCompat.h: add AD_WEAK macro.

Verified: final armv6 binary has zero undefined objc_retain/release/storeStrong/
retainAutoreleasedReturnValue imports and zero undefined blocks/GCD imports.
Produces a valid <NOUNDEFS> Mach-O armv6 IPA + Cydia deb.
- README.md: rewrite to describe the ARC->MRC conversion (24 __weak sites ->
  AD_WEAK/__unsafe_unretained, 2 weak properties -> assign), drop the ARC-shim
  narrative. Blocks + GCD shims remain (iOS 3 has neither runtime regardless).
- AppDropCompat.h: refresh the prefix-header banner to match (no ARC runtime
  shim / libarclite; -fno-objc-arc; native retain/release).
- gcd_shim.c: dispatch_queue_create now returns a true single-worker FIFO
  serial queue (concurrent only for the global queue / DISPATCH_QUEUE_CONCURRENT).
  Fixes LocalCatalog _searchQueue racing one sqlite3* handle.
- Info.plist: MinimumOSVersion 5.0 -> 3.0, removed UIRequiredDeviceCapabilities armv7.
- README: marked the serial-queue and plist items resolved.
SpringBoard rejected the bundle ("does not have an executable path")
because Info.plist declared CFBundleExecutable=AppDrop while build.sh
produces a binary/.app named IPAInstaller (APP_NAME). The actual exec
inside the .app is 'IPAInstaller', so SB couldn't resolve it and killed
the launch. CFBundleDisplayName/CFBundleName stay 'AppDrop' (user-facing).
…back to AppDrop

Crash on iPod touch / iOS 3.1.3:
  Dyld: Symbol not found: _imp_implementationWithBlock (libobjc.A.dylib)
imp_implementationWithBlock first shipped in iOS 4.3, so the app aborted
at launch before main(). AppDropRuntime.m installed its backfilled IMPs
via imp_implementationWithBlock(); rewrote all of them as plain static C
functions (id self, SEL _cmd, ...) passed straight to class_addMethod()
with identical type encodings — no block trampoline, no missing symbol.
AppDropJSON.m already used this safe style.

Also:
- build-ios3.sh: APP_NAME back to 'AppDrop' (per request), so binary +
  .app are AppDrop and match CFBundleExecutable=AppDrop again. Source
  folder stays IPAInstaller/.
- Info.plist: CFBundleExecutable reverted to AppDrop.
- build-ios3.sh: leaked-symbol guard now also catches imp_implementationWithBlock
  / imp_removeBlock so this class of iOS-3 launch crash can't ship silently.
- README: documented both fixes.
The app crashed at launch on iOS 3.1.3 with an uncaught NSException
(objc_exception_throw -> terminate -> SIGABRT, fired from inside
UIApplicationMain). Root cause: AppDelegate's tab-bar icon builders
(AppDropHomeTabIcon/AppDropFavoritesTabIcon) read
[UIScreen mainScreen].scale before anything is on screen.
-[UIScreen scale] is an iOS 4.0 selector and is an unrecognized
selector on 3.1.3.

Backfill three iOS 4.0 graphics APIs in AppDropRuntime.m, all no-ops
on iOS 4+ where the OS already provides them:
  * -[UIScreen scale]            -> 1.0 (all armv6 devices are 1x)
  * -[CALayer contentsScale]/set -> 1.0 / no-op (AppTileView grid)
  * UIGraphicsBeginImageContextWithOptions (C fn) -> defined in-binary
    so the static linker has no undefined iOS-4 UIKit import (would
    abort dyld on iOS 3); forwards to the real UIKit impl via RTLD_NEXT
    on iOS 4+, falls back to UIGraphicsBeginImageContext on iOS 3.

Verified end-to-end: cross-build links a NOUNDEFS armv6 Mach-O and
llvm-nm confirms UIGraphicsBeginImageContextWithOptions is now a
defined (T) symbol, not an undefined import.
…time

Second launch crash on iOS 3.1.3 (after the UIScreen-scale fix let the app
reach setupAppearance):

  *** -[NSCFDictionary objectForKeyedSubscript:]: unrecognized selector

Modern subscripting (dict[key], arr[i], and their setters) is an iOS 6 SDK
feature with no runtime support on iOS 3.1.3. The IMPs lived in IOS5Compat.m,
but the iOS3 build explicitly excludes that file ('replaced by
AppDropRuntime.m') and the subscript trampolines were never ported over — so
EVERY dict[key]/arr[i] on-device threw unrecognized selector. The first one
hit is launchOptions[...] / theme dict access in the launch path.

Port the four proven trampolines from IOS5Compat.m into AppDropRuntime.m so
they install via +load and cover all call sites app-wide:
  - NSDictionary  -objectForKeyedSubscript:      (@@:@)
  - NSMutableDictionary -setObject:forKeyedSubscript:  (v@:@@)
  - NSArray  -objectAtIndexedSubscript:          (@@:L)
  - NSMutableArray -setObject:atIndexedSubscript: (v@:@l)

Each is guarded by instancesRespondToSelector: so it's a no-op on iOS 5+.
Verified: armv6 build links NOUNDEFS, leaked-symbol guard passes, all four
trampolines present in the binary.
…r (iOS 4.0)

Third launch crash on iOS 3.1.3 (now past setupAppearance/window alloc, dies
building the Catalogue list in 'alloc CatalogVC'):

  *** -[NSCFArray sortUsingComparator:]: unrecognized selector
  *** -[UIWindow setRootViewController:]: unrecognized selector

Both are iOS 4.0 APIs present in the 5.1 SDK headers (so the source compiles)
but absent from the 3.1.3 runtime. Added to AppDropRuntime.m via +load:

  - NSMutableArray -sortUsingComparator: / NSArray -sortedArrayUsingComparator:
    bridged to the iOS-2 sortUsingFunction:context: APIs via a C trampoline that
    invokes the NSComparator block passed as context.
  - UIWindow -rootViewController / -setRootViewController: backed by an
    associated object; the setter installs the controller's view as the window's
    content subview (the iOS 4 behaviour), removing any previous one.

Verified: armv6 build links NOUNDEFS, leaked-symbol guard passes, all four
trampolines present in the binary.
…or iOS 3.1

UIBezierPath debuts in iOS 3.2; on 3.1.3 the class symbol exists but its
drawing methods are unimplemented, so the first tab glyph drawn at launch
threw -[UIBezierPath addLineToPoint:]: unrecognized selector, the launch
@Try caught it, and SpringBoard showed "AppDrop failed to launch".

Ship ADBezierPath: a complete CGPath-backed replacement using only iOS-2-era
CoreGraphics (bezierPath/WithRect/WithOvalInRect/WithRoundedRect:cornerRadius,
moveToPoint/addLineToPoint/closePath/fill/stroke/addClip/CGPath + lineWidth/
cap/join/even-odd). AppDropCompat.h #defines UIBezierPath -> ADBezierPath so
all 9 call sites switch with zero source edits; AppDropBezier.m is wired into
build-ios3.sh. Same self-contained strategy as AppDropJSON.m's NSJSONSerialization.
…(AD*GestureRecognizer)

UILongPressGestureRecognizer/setMinimumPressDuration: and the whole
gesture subsystem (incl. -[UIView addGestureRecognizer:]) are iOS 3.2+.
On 3.1.3 the classes alloc but the methods are stubs -> unrecognized
selector -> SIGABRT right after makeKeyAndVisible.

Backport mirrors the ADBezierPath approach:
- compat/AppDropGestures.m: real AD{,Tap,LongPress,Pan}GestureRecognizer
  classes + a UIWindow -sendEvent: dispatch engine (walks hit-view
  superview chain, feeds touches to attached recognizers).
- AppDropCompat.h: declares the AD* interfaces and macro-rewrites the
  UIKit class names onto them.
- build-ios3.sh: compile compat_gestures.o.
Keeps every tap/long-press/pan working (not just a crash guard).
Uses only iOS 2.0-era primitives already proven at launch.
…FRunLoopTimer in GCD main-queue hop

dyld aborted at launch (SIGTRAP): Symbol not found: _CFRunLoopPerformBlock.
gcd_shim.c run_on_main() scheduled main-queue blocks via CFRunLoopPerformBlock,
which first ships in iOS 4.0 / CoreFoundation 550 — absent on 3.1.3. Replaced
with a one-shot CFRunLoopTimer (CFRunLoopTimerCreate, available since iOS 2.0)
fired immediately on the main run loop; the copied block rides in the timer
context and is run+released in the callback, then the timer self-invalidates.

Also added a build-script guard that fails if CFRunLoopPerformBlock ever
reappears as an undefined import (resolves vs the 5.1 SDK but missing at runtime
on 3.1.3). Updated ios3/README.
…releasePool

The app launched on iOS 3.1.3 then crashed ~2s later with EXC_BAD_ACCESS
(SIGBUS) in objc_msgSend on a background thread (Thread 3). Root cause:
LocalCatalog dispatches catalog-DB work onto its serial _searchQueue and the
global background queue at launch; those queues are backed by gcd_shim.c
pthread workers, which executed the ObjC blocks with no NSAutoreleasePool on
the thread. Under MRC on iOS 3 there is no implicit per-thread pool, so every
autoreleased Foundation object leaked (device log floods with
_NSAutoreleaseNoPool: ... just leaking) and the runtime eventually faulted.

Fix: wrap every block run on a shim-spawned thread in its own NSAutoreleasePool
via a new ad_invoke() helper (trampoline, serial_worker, after_thread,
group_async_thread, group_notify_thread, and inline fallbacks). Pool is driven
through the objc runtime C API since the shim is C; NSAutoreleasePool is iOS
2.0 and always present.
…(Block_copy)

The static libclosure shim never gets _Block_use_RR called, so its default
object retain/release callouts were no-ops. Block_copy therefore did not
retain Objective-C objects captured by a block; the capturing autorelease
scope freed them, and a dispatch_async(main_queue) block firing off the
main CFRunLoopTimer messaged a dangling pointer -> EXC_BAD_ACCESS in
objc_msgSend on Thread 0. Make the default callouts send -retain/-release
via the objc C API (objc_msgSend + sel_registerName), as real _Block_use_RR
would.
…atch_after main-queue path

The objc_msgSend EXC_BAD_ACCESS on Thread 0 (~0.6s after makeKeyAndVisible,
the deferred catalog-quality alert) was a double-release of the deferred
block in dispatch_after. The old main-queue path wrapped the user block mb in
^{ run_on_main(Block_copy(mb)); Block_release(mb); }. The blocks runtime
already retains mb on the wrapper's Block_copy and releases it via the
wrapper's dispose helper, so the manual Block_release(mb) over-released it:
mb (and its captured AppDelegate self + alert strings) was freed early, and
the main CFRunLoopTimer later messaged the dangling objects -> crash.

Drop the wrapper: dispatch_after now stores the single Block_copy'd block plus
an is_main flag, and after_thread hands that one ref to run_on_main (which
owns + releases it after its one-shot timer fires) for the main queue, or
runs+releases inline otherwise. No second copy, no over-release.
dyld aborted at launch with 'can't resolve symbol _CGImageSourceCreateWithData
... because dependent dylib AdrienRL1#5 could not be loaded' (EXC_BREAKPOINT, SIGTRAP).

dylib AdrienRL1#5 is ImageIO. The iOS 5.1 SDK linker records it at the iOS-5 public
location /System/Library/Frameworks/ImageIO.framework/ImageIO, but on iOS 3.1.3
ImageIO is a PRIVATE framework at /System/Library/PrivateFrameworks/. dyld
couldn't find it at the public path, failed to load the dependent dylib, and
thus couldn't resolve the ImageIO symbols IconLoader.m lazily binds (used by
-decodeAndResize:targetSize:), aborting in dyld.

Fix in build-ios3.sh:
- build install_name_tool from cctools-port (alongside ld64/lipo/strip)
- link with -headerpad_max_install_names so the longer path fits
- install_name_tool -change the ImageIO load command to the PrivateFrameworks
  path (runs before .app bundling and ldid signing)
- add a toolchain-independent guard that greps the binary: public /Frameworks/
  path must be gone, /PrivateFrameworks/ path must be present
TimofeyLednev and others added 27 commits June 11, 2026 22:36
Pulls the full 3.2.0.3 feature set (StatsClient download counts,
Most Downloaded shortcut, upload.appdrop.ca, ios5_rebind post-link
fix, localization updates) while keeping the iOS 3 backport:
- Makefile: upstream AppDrop_FILES + StatsClient.m, kept MRC flags
  (-fno-objc-arc, AD_WEAK, AppDropBlocks.h prefix) and ios3 compat
  include paths alongside upstream's ios5_rebind/visibility changes
- control: version 3.2.0.3 with the iOS3-branch metadata kept
The upstream v3.2 merge brought in ARC constructs the MRC build
(-fno-objc-arc) rejects — both CI jobs failed on the same error:
'cannot synthesize weak property in file using manual reference
counting' (armv7) / 'deployment target does not support weak
references' (armv6).

- CategoryViewController: @Property(weak) topDLTile -> assign
  (non-owning back-ref to a tile owned by self.tiles; same fix the
  iOS3 backport applied to the 2 original weak properties, per
  ios3/README.md)
- StatsClient: __weak typeof(self) -> AD_WEAK (the branch-wide
  non-zeroing weak macro), and __bridge_transfer CFUUID string ->
  explicit retain/autorelease + CFRelease (no ownership bridges
  under MRC)
Two after-stage failures on a fresh CI runner (no build-toolchain/bin):
- 'plutil: command not found' -> all Localizable.json FAILED. Add
  tools/strings2json.py (same .strings->JSON conversion build-ios3.sh
  does inline, utf-8/utf-16 aware) and use it whenever plutil is absent.
- ios5_rebind.py ran against .app/AppDrop, which at that point is the
  AppDropLauncher.sh shell script ('not a 32-bit little-endian Mach-O',
  magic 622f2123 = '#!/b'). Point ios5_rebind + ldid at AppDrop.armv7,
  the actual armv7 binary after the launcher rename.
@TimofeyLednev TimofeyLednev changed the title iOS 3 Support Add iOS 3 Support Jun 12, 2026
@Epixx512

Copy link
Copy Markdown

*iPhone OS 3

@TimofeyLednev TimofeyLednev changed the title Add iOS 3 Support Add iPhone OS 3 Support Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants