Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ゲームボーイアドバンスでSwiftを動かそう

k-kohey
August 23, 2024

 ゲームボーイアドバンスでSwiftを動かそう

2024/08/23 13:55〜
Track D
レギュラートーク(20分)

https://fortee.jp/iosdc-japan-2024/proposal/d83218af-4607-4f63-9e21-1d2f3f102a46

k-kohey

August 23, 2024
Tweet

More Decks by k-kohey

Other Decks in Programming

Transcript

  1. എܠc4XJGUΛ࢖ͬͨ૊ΈࠐΈ։ൃͷࣄྫ w TXJGUPSHʹ༷ͯʑͳϚΠίϯ্Ͱ 4XJGUίʔυΛಈ͔͢ࣄྫͷ঺հ͕͞Εͨ<> w 4XJGUΛ࢖ͬͯ૊ΈࠐΈ։ൃΛߦ͏ηογϣϯ͕ 88%$Ͱެ։͞Εͨ<> w "QQMF͸4FDVSF&ODMBWFϓϩηοαͷ։ൃʹ 4XJGUΛ༻͍͍ͯΔ<>

     <>IUUQTXXXTXJGUPSHCMPHFNCFEEFETXJGUFYBNQMFT<>IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED<>IUUQT XXXTXJGUPSHCMPHFNCFEEFETXJGUFYBNQMFT<>IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED <>ʹެ։͞Εͨ4XJGUΛ࢖ͬͨ૊ΈࠐΈ։ൃͷ༷ࢠ
  2. എܠc4XJGUΛ࢖ͬͨ૊ΈࠐΈ։ൃͷࣄྫ w TXJGUPSHʹ༷ͯʑͳϚΠίϯ্Ͱ 4XJGUίʔυΛಈ͔͢ࣄྫͷ঺հ͕͞Εͨ<> w 4XJGUΛ࢖ͬͯ૊ΈࠐΈ։ൃΛߦ͏ηογϣϯ͕ 88%$Ͱެ։͞Εͨ<> w "QQMF͸4FDVSF&ODMBWFϓϩηοαͷ։ൃʹ 4XJGUΛ༻͍͍ͯΔ<>

     <>IUUQTXXXTXJGUPSHCMPHFNCFEEFETXJGUFYBNQMFT<>IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED<>IUUQT XXXTXJGUPSHCMPHFNCFEEFETXJGUFYBNQMFT<>IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED <>ʹެ։͞Εͨ4XJGUΛ࢖ͬͨ૊ΈࠐΈ։ൃͷ༷ࢠ ࠓ೥ಛʹ੝Γ্͕͍ͬͯΔٕज़
  3. എܠc4XJGUΛ࢖ͬͨϨτϩήʔϜ։ൃ w ϨτϩήʔϜ։ൃ͸૊ΈࠐΈ։ൃͷҰछ w ։ൃࣄྫ w 1MBZEBUFʢൃϨτϩήʔϜ෩ܞଳήʔϜػʣ w 4XJGUΛ࢖ͬͨαϯϓϧίʔυͱղઆهࣄ͕ެ։͞Ε͍ͯΔ<> w

    ήʔϜϘʔΠΞυόϯεʢҎ߱ɼ(#"ʣ w 9ʹͯ4XJGUΛ(#"Ͱಈ͔ͨ͠ใࠂ͕͋ͬͨ<> w ͨͩ͠۩ମతͳݪཧ΍ํ๏ͷݴٴ͸ͳ͔ͬͨ w ʢϓϩϙʔβϧక੾࣌఺ʣʹͯଞʹ4XJGUΛ࢖ͬͯ (#"։ൃΛߦͬͨࣄྫ΍ղઆهࣄ͸ݟ౰ͨΒͳ͔ͬͨ<>  <>IUUQTXXXTXJGUPSHCMPHCZUFTJ[FETXJGUUJOZHBNFTQMBZEBUF <>IUUQTYDPNIBSMBOIBTLJOTTUBUVT <>ࣗ෼ௐ΂ (#"ͷᝑମ IUUQTXXXOJOUFOEPDPKQOIBSEXBSFHCBJOEFYIUNM 1MBZEBUFͷᝑମ IUUQTQMBZEBUFTIPQ
  4. എܠc4XJGUΛ࢖ͬͨϨτϩήʔϜ։ൃ w ϨτϩήʔϜ։ൃ͸૊ΈࠐΈ։ൃͷҰछ w ։ൃࣄྫ w 1MBZEBUFʢൃϨτϩήʔϜ෩ܞଳήʔϜػʣ w 4XJGUΛ࢖ͬͨαϯϓϧίʔυͱղઆهࣄ͕ެ։͞Ε͍ͯΔ<> w

    ήʔϜϘʔΠΞυόϯεʢҎ߱ɼ(#"ʣ w 9ʹͯ4XJGUΛ(#"Ͱಈ͔ͨ͠ใࠂ͕͋ͬͨ<> w ͨͩ͠۩ମతͳݪཧ΍ํ๏ͷݴٴ͸ͳ͔ͬͨ w ʢϓϩϙʔβϧక೔࣌఺ʣʹͯଞʹ4XJGUΛ࢖ͬͯ (#"։ൃΛߦͬͨࣄྫ΍ղઆهࣄ͸ݟ౰ͨΒͳ͔ͬͨ<>  <>IUUQTXXXTXJGUPSHCMPHCZUFTJ[FETXJGUUJOZHBNFTQMBZEBUF <>IUUQTYDPNIBSMBOIBTLJOTTUBUVT <>ࣗ෼ௐ΂ (#"ͷᝑମ IUUQTXXXOJOUFOEPDPKQOIBSEXBSFHCBJOEFYIUNM 1MBZEBUFͷᝑମ IUUQTQMBZEBUFTIPQ 4XJGUͰ(#"։ൃͷ৘ใ͸গͳ͍
  5. ໨తc໨࣍ w എܠ w ໨త w ࣗݾ঺հ w ൃදͷείʔϓ w

    ಈ࡞ݪཧ w ։ൃ؀ڥߏங w αϯϓϧίʔυ w ·ͱΊ 
  6. ࣗݾ঺հ w ιʔγϟϧΞΧ΢ϯτ w (JU)VCɿLLPIFZ w 9ɿL@LPIFZJ w ॴଐ w

    גࣜձࣾϦΫϧʔτ w J04ΤϯδχΞ w (#"ͷιϑτ͸։ൃ͍ͯ͠ͳ͍ 
  7. ൃදͷείʔϓ w ࿩͢͜ͱ w 4XJGUΛ(#"޲͚ʹίϯύΠϧ͢Δݪཧͱํ๏ w ίϯύΠϧ͢Δࡍʹର໘͢ΔΤϥʔͷղܾํ๏ w ը໘ඳը΍ϘλϯೖྗͳͲͷ(#"ͷجຊతͳ࢓༷ͱ࣮૷ํ๏ w

    ࿩͞ͳ͍͜ͱ w ήʔϜ։ൃͷϊ΢ϋ΢ w 4XJGUίϯύΠϥͷ಺෦࣮૷΍मਖ਼ํ๏ʹ͍ͭͯ w طଘͷπʔϧνΣʔϯͷΈͰ࣮૷͕Մೳ 
  8. ಈ࡞ݪཧc(#"ͷΞʔΩςΫνϟ޲͚ʹίϯύΠϧ w --7.͸"3.WUʹ޲͚ʹग़ྗͰ͖ΔόοΫΤϯυΛ͍࣋ͬͯΔ w (#"͸"3.WUΞʔΩςΫνϟΛ࠾༻͍ͯ͠Δ  4XJGU ϑϩϯτΤϯυ Y --7.*3

    3*4$7 "3.WU Y όοΫΤϯυ 3*4$7 όοΫΤϯυ "3. όοΫΤϯυ --7.όοΫΤϯυͷ࢓૊ΈʹΑͬͯ 4XJGUΛ(#"ͷΞʔΩςΫνϟʹ޲͚ʹ ίϯύΠϧ͢Δࣄ͕Մೳ
  9. ಈ࡞ݪཧc(#"ͷ30.Λੜ੒ w (JU)VCʹެ։͞Ε͍ͯΔ--7.ϕʔεͷ(#"։ൃ༻ͷπʔϧνΣʔϯ HCBMMWNEFWLJUΛ࢖͏ w (#"Ͱಈ࡞͢Δ30.Λੜ੒͢Δͷʹඞཁͳ ҎԼͷΑ͏ͳπʔϧ͕ఏڙ͞Ε͍ͯΔ w ελʔτΞοϓίʔυ w

    ϓϩάϥϜ࣮ߦ։࢝લͷॳظԽॲཧ౳ w ϦϯΧεΫϦϓτ w ϦϯΫ࣌ͷγϯϘϧͷ഑ஔ౳ w HCB fi Y w ϔομʔ৘ใͷमਖ਼΍ݕূɽϔομʔ͕ؒҧ͍ͬͯΔͱ࣮ػͰىಈͰ͖ͳ͍<>  <>IUUQTBLLFSBTBLVSBOFKQHCBEFW '"2WE
  10. ಈ࡞ݪཧc(#"ͷ30.Λੜ੒ w (JU)VCʹެ։͞Ε͍ͯΔ--7.ϕʔεͷ(#"։ൃ༻ͷπʔϧνΣʔϯ HCBMMWNEFWLJUΛ࢖͏ w (#"Ͱಈ࡞͢Δ30.Λੜ੒͢Δͷʹඞཁͳ ҎԼͷΑ͏ͳπʔϧ͕ఏڙ͞Ε͍ͯΔ w ελʔτΞοϓίʔυ w

    ϓϩάϥϜ࣮ߦ։࢝લͷॳظԽॲཧ౳ w ϦϯΧεΫϦϓτ w ϦϯΫ࣌ͷγϯϘϧͷ഑ஔ౳ w HCB fi Y w ϔομʔ৘ใͷमਖ਼΍ݕূɽϔομʔ͕ؒҧ͍ͬͯΔͱ࣮ػͰىಈͰ͖ͳ͍<>  <>IUUQTBLLFSBTBLVSBOFKQHCBEFW '"2WE "3.WU޲͚ʹίϯύΠϧ͢Δઃఆͱ ͜ΕΒͷ(#"ͷ30.Λਖ਼͘͠ੜ੒͢ΔͨΊͷ ޻෉Λ૊Έ߹ΘͤΔ
  11. ։ൃ؀ڥߏஙc։ൃπʔϧͷΠϯετʔϧ w TXJGUͷUPPMDIBJO w NBJOCSBODIͰ։ൃதͷTXJGUΛTXJGUPSH͔ΒΛೖखͰ͖Δ<> w TXJGU%&7&-01.&/54/"14)05BΛ࢖༻ w HCBMMWNEFWLJU w

    (JU)VCͷ3FMFBTFT͔ΒೖखͰ͖Δ<> w SFMFBTFWΛ࢖༻ w ΤϛϡϨʔλ w N(#"Λ࢖༻<>  <>IUUQTXXXTXJGUPSHEPXOMPBE <>IUUQTHJUIVCDPNTUVJKHCBMMWNEFWLJUSFMFBTFTUBHSFMFBTFW <>IUUQTNHCBJP
  12. ։ൃ؀ڥߏஙc(#"޲͚ʹίϯύΠϧ w TXJGUDίϚϯυΛ࢖ͬͯ(#"ͷΞʔΩςΫνϟΛࢦఆ͢Δ w swiftc -o my_game.elf EntryPoint.swift -target armv4t-none-none-eabi

    w &NCFEEFE4XJGUΛ༗ޮ w swiftc -o my_game.elf EntryPoint.swift -wmo -enable-experimental-feature Embedded -target armv4t-none-none-eabi 
  13. ։ൃ؀ڥߏஙc(#"޲͚ʹίϯύΠϧ w HCBMMWNEFWLJUͷ3&"%.&ʹॻ͔ΕͨDMBOH޲͚ͷΦϓγϣϯ<> w clang --config armv4t-gba.cfg -Wl,-T,gba_cart.ld program.c -o

    program.elf w ্هͷΦϓγϣϯΛTXJGUDʹ௥Ճ w swiftc -o my_game.elf EntryPoint.swift -wmo -enable-experimental- feature Embedded -target armv4t-none-none-eabi -parse-as-library -Xcc -mthumb -Xcc -mfpu=none -Xcc -fno-exceptions -Xcc -fno-rtti -Xcc -D_LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT -Xcc -fshort-enums -Xlinker -lcrt0-gba -Xclang-linker -T -Xclang-linker gba_cart.ld -Xclang-linker --sysroot -Xclang-linker path/to/gba-llvm-devkit-1- Darwin-arm64/lib/clang-runtimes/arm-none-eabi/armv4t  <>IUUQTHJUIVCDPNTUVJKHCBMMWNEFWLJUCMPCF ff EDGBBCBGEECDFGFCDED3&"%.&NE QMBJO-
  14. ։ൃ؀ڥߏஙcίϯύΠϧΤϥʔͷղܾ w ҎԼͷΤϥʔͰϦϯΫʹࣦഊʢϦϯΫ·Ͱ͸੒ޭͨ͠ʣ w @@BUPNJD@@ γϯϘϧ͕͍͔ͭ͘ݟ͔ͭΒͳ͍  MEMMEFSSPSVOEF fi OFETZNCPM@@BUPNJD@MPBE@

    SFGFSFODFECZNZ@HBNFP WBSGPMEFSTLI[@TDEURZY@RSINHO55FNQPSBSZ%JSFDUPSZQRP1NZ@HBNFP TTTXJGU@SFUBJOPCKFDU#Q#Q@U'  SFGFSFODFECZNZ@HBNFP WBSGPMEFSTLI[@TDEURZY@RSINHO55FNQPSBSZ%JSFDUPSZQRP1NZ@HBNFP TTTXJGU@SFMFBTFPCKFDUZ#Q@U'  SFGFSFODFECZNZ@HBNFP WBSGPMEFSTLI[@TDEURZY@RSINHO55FNQPSBSZ%JSFDUPSZQRP1NZ@HBNFP TTTXJGU@SFUBJO@OPCKFDUO#Q#Q@T6*OU7U'  SFGFSFODFENPSFUJNFT MEMMEFSSPSVOEF fi OFETZNCPM@@BUPNJD@GFUDI@BEE@ SFGFSFODFECZNZ@HBNFP WBSGPMEFSTLI[@TDEURZY@RSINHO55FNQPSBSZ%JSFDUPSZQRP1NZ@HBNFP TTTXJGU@SFUBJOPCKFDU#Q#Q@U'  SFGFSFODFECZNZ@HBNFP WBSGPMEFSTLI[@TDEURZY@RSINHO55FNQPSBSZ%JSFDUPSZQRP1NZ@HBNFP TTTXJGU@SFUBJO@OPCKFDUO#Q#Q@T6*OU7U'  ҎԼུ
  15. ։ൃ؀ڥߏஙcίϯύΠϧΤϥʔͷղܾ w TUEPVU΋γϯϘϧ͕ݟ͔ͭΒͳ͍ͱΤϥʔʹͳ͍ͬͯͨ w MJCDͷQVUDIBSD͔Βࢀর͞Ε͍ͯΔ w ҰํͰ(#"্Ͱඪ४ग़ྗ͸࢖Θͳ͍ͷͰҎԼͷΑ͏ʹۭ࣮૷Λ௥Ճ w !@TJMHFO@OBNF<>Λ࢖ͬͯϚϯάϦϯάΛճආ͢Δ 

    @_silgen_name("stdout") let stdout: UnsafeMutableRawPointer? = nil <>IUUQTHJUIVCDPNTXJGUMBOHTXJGUCMPCNBJOEPDT3FGFSFODF(VJEFT6OEFSTDPSFE"UUSJCVUFTNE@TJMHFO@OBNFSBXDOBNF
  16. ։ൃ؀ڥߏஙc.BLFGJMFͱ1BDLBHFTXJGUͷ௥Ճ w Ұ࿈ͷεΫϦϓτΛ.BLF fi MFʹ·ͱΊΔ w ͋Δ4XJGUϑΝΠϧ͔ΒଞͷϑΝΠϧͷγϯϘϧ Λίʔυิ׬͔Β ࢀরͰ͖ΔΑ͏ʹ4XJGU1BDLBHFʹϑΝΠϧΛ ·ͱΊΔ

    w 1BDLHFTXJGUʹॻ͘ίϯύΠϧͷઃఆ͸.BLF fi MFͱ େମಉ͡Α͏ʹ͢Δ  $(NAME).gba: $(NAME).elf $(BIN)/llvm-objcopy -O binary $^ $@ $(BIN)/gbafix $@ $(NAME).elf: $(SWIFT_FILES) $(SC) -o $@ $(SWIFT_FILES) \ $(SWIFT_FLAGS) $(addprefix -Xcc , $(CFLAGS)) \ $(addprefix -Xlinker , $(LFLAGS)) \ $(addprefix -Xclang-linker , $(CLANG_LINKER_FLAGS)) run: $(NAME).gba make mGBA $< .PHONY: all clean run clean: rm -f *.o *.elf *.gba *.bc let package = Package( name: "my_game", platforms: [.macOS(.v14)], products: [ .library( name: "my_game", targets: ["my_game"] ) ], dependencies: [], targets: [ .target( name: "my_game", dependencies: [], publicHeadersPath: "include", cSettings: [ .define("_LIBCPP_AVAILABILITY_HAS_NO_VERBOSE _ABORT"), .unsafeFlags(["-O3", "-mthumb", "- mfpu=none", "-fno-exceptions", "-fno-rtti", "-fshort- enums"]) ಺༰͸Ұ෦ൈਮͨ͠΋ͷ
  17. αϯϓϧc#JUNBQ.PEFͷ࢓༷ w 7JEFP3".ʢҎ߱73".ʣͱ͍͏ϝϞϦྖҬʹ CJUͷ৭৘ใΛॻ͖ࠐΉͱΞυϨεʹ ରԠ͢Δը໘্ͷϐΫηϧʹ৭͕ඳը͞ΕΔ w 73".ͷઌ಄ΞυϨεʢIʣ͸ ը໘ࠨ্ͷϐΫηϧʹ֘౰͢Δ w ΞυϨεΛCJUͣͭਐΊΔ͝ͱʹ

    ϐΫηϧͣͭඳըର৅͕ӈଆʹҠಈ͢Δ w ઌ಄ΞυϨε͔ΒCJU QYʢԣ෯ʣ ਐΊΔ͝ͱʹϐΫηϧԼଆʹҠಈ͢ΔʢંΓฦ͢ʣ  ԣ෯QY ॎ ෯    Q Y I %&I
  18. αϯϓϧcॲཧͷྲྀΕ w ࢢদ໛༷ͷࠇͱ྘ͷྖҬͷॎԣΛͦΕͧΕQYͱͯ͠ɼ ը໘ͷࠨ্͔ΒӈԼʹ޲͚֤ͯྖҬຖʹ4DSFFO8SJUFSΛհͯ͠৭Λॻ͖ࠐΉ  let screenWriter = ScreenWriter() let

    rectSize = Size(width: 10, height: 10) for y in 0..<(Screen.height / rectSize.height) { for x in 0..<(Screen.width / rectSize.width) { let color: Color = (x + y) % 2 == 0 ? .black : .green screenWriter.draw( color, at: .init( x: x * rectSize.width, y: y * rectSize.height), size: rectSize ) } } QY QY QY ࢢদ໛༷ͷࠇͱ྘ͷྖҬ
  19. αϯϓϧc73".ʹॻ͖ࠐΉϝιου w 4DSFFO8SJUFSͷESBXϝιου಺ʹͯߦͣͭCJUͷ৭Λॻ͖ࠐΜͰ͍͘  func draw(_ color: Color, at origin:

    Position, size: Size) { let color16 = color.to16Bit() //தུ for y in startY..<endY { let rowStartIndex = y * Screen.width + startX let count = endX - startX let destination = vram.advanced(by: rowStartIndex) destination.initialize(repeating: color16, count: count) } }
  20. αϯϓϧc5JMF.PEFͷ࢓༷ w 4QSJUF͸ཁૉʹ෼͚ͯϝϞϦʹॻ͖ࠐΉʹΑͬͯඳը͞ΕΔ w 1BMFUUF3".ʢYʣ w ࢖༻͢Δ৭Λهड़ w 73".ʢYʣ w

    #JUNBQ.PEFͱҟͳΓ۩ମతͳ3(#ͷ஋͸࣋ͨͳ͍ w 1BMFUUFͰఆٛ͞Εͨ৭Λ5JMF্ͷͲ͜ʹ഑ஔ͞ΕΔ͔Λهड़ w 0CKFDU"UUSJCVUF.FNPSZʢYʣ w Ґஔ΍େ͖͞౳ͷඳ͔ΕํΛهड़ 
  21. αϯϓϧc4QSJUFσʔλͷ࡞੒ w 4QSJUF͸όΠφϦͱͯ͠ιʔείʔυ্ʹఆٛ͢Δ w HSJUίϚϯυΛ࢖͏͜ͱʹΑͬͯը૾͔Β όΠφϦͷఆ͕ٛ͞Εͨ$ϑΝΠϧΛੜ੒Ͱ͖Δ  Y Y Y

    Y  Y Y Y Y  Y Y Y Y  Y Y Y Y Y Y Y  Y Y Y Y  Y Y Y  Y Y Y Y  Y Y Y Y  Y Y Y Y  Y Y Y Y Y Y Y  Y Y Y Y  Y Y Y Y  Y HSJUDIBSBDUFSQOH H#.X.IGUD DIBSBDUFSQOH DIBSBDUFSD
  22. αϯϓϧc4QSJUFͷಡΈࠐΈ w $Ͱੜ੒͞Εͨ5JMFΛ4XJGUͰఆٛͨ͠.FNUJMF<>ʢ73".ʣʹॻ͖ࠐΉ w .FNUJMF<>d.FNUJMF<>ʹରԠ͢ΔΞυϨε͸എܠ༻ͷ5JMFʹ࢖ΘΕΔ w $Ͱੜ੒͞Εͨ5JMFͷ৭৘ใΛهड़ͨ͠1BMFUUFΛ .FNQBMʢ1BMFUUF3".ʣʹॻ͖ࠐΉ  withUnsafePointer(to:

    characterTiles) { characterTilesPointer in characterTilesPointer.withMemoryRebound(to: CHARBLOCK.self, capacity: 1) { source in Mem.tile[4] = source.pointee } } withUnsafePointer(to: characterPal) { pointer in pointer.withMemoryRebound(to: UInt16.self, capacity: 256) { uint16Pointer in Mem.pal.update(from: uint16Pointer, count: 256) } }
  23. αϯϓϧcUPODͷར༻ w 5PODʢUPODʣ͸(#"։ൃʹؔ͢ΔςΩετ͓ΑͼϥΠϒϥϦ<> w ࣮૷Λ؆୯ʹ͢ΔͨΊʹUPODΛར༻͢Δ w UPODΛϦϯΫ͢Δ w -Xlinker -ltonc

    w UPODͷϔομʔϑΝΠϧͷ৔ॴΛ఻͑Δ w -I$path/to/include w 4XJGU͔Βར༻Ͱ͖ΔΑ͏ʹ#SJEHJOH)FBEFSΛॻ͘ w -import-objc-header Bridging-Header.h  <>IUUQTXXXDPSBOBDDPNUPODUFYU