Skip to content

Conversation

@quinnyo
Copy link
Contributor

@quinnyo quinnyo commented Apr 27, 2024

This PR adds a lesson on the serial port to resolve #42.

Still a draft because the lesson text needs to be updated.

About the implementation:
Sio (sio.asm) is a kind of multi-byte version of the underlying GB serial API.

  • implements the timeout for the externally clocked device
  • implements the clock provider's "catchup delay"
  • a data integrity test for received packets is included, using a rather simple checksum

main.asm is based on the BCD unbricked code.

  • each peer sends its current score to the other and the remote peer's score is displayed below the local one.
  • an initial handshake is performed to establish the connection (automatically determines the clock provider)
  • there's no attempt made to guarantee delivery of packets but if a corrupt or non-sequential packet arrives, the connection is terminated.
  • To build it you just need to compile and link both main.asm and sio.asm.

demo.asm is a standalone test rom I used to test and debug the serial transfer implementation. It isn't part of the lesson and can be removed if necessary, but it provides more debug information than the integration with unbricked.

; :: / `--<[|]= |[ m ]|| ::
; :: \ .______ | ```` || ::
; :: / !| `````| | + oo|| ::
; :: ( ||[ ^u^]| | .. #|| ::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this!

@quinnyo quinnyo force-pushed the part2pointserial branch from add7190 to 0352ed2 Compare May 9, 2024 17:34
@quinnyo quinnyo force-pushed the part2pointserial branch 2 times, most recently from 3a0e30d to 431baff Compare June 26, 2024 22:31
@quinnyo

This comment was marked as outdated.

@avivace avivace requested a review from Rangi42 July 7, 2024 19:32
@avivace
Copy link
Member

avivace commented Jul 12, 2024

The code has been updated a bit. I updated the PR comment to reflect the changes. I don't think there are any glaring holes in the implementation and it works consistently in my simple test program. (so I need to improve the test!)

I'm not sure how this should be integrated with the unbricked code, or if I need to provide something more significant for testing purposes?

I didn't want to add test code to this repo, so I've been working on the impl in a standalone project (https://github.com/quinnyo/gbserial). sio.asm in this PR should be the same as in that repo at time of writing. The current program is a simple test where the two devices yell at each other. You first need to press START to toggle clock source on one GB. You get a tick if the checksum of the received packet checks OK, F for uhh, "big Fail" (timed out / incomplete packet). The relevant test bits are in sio_demo.asm.

Not sure about more significant testing, but I'd start thinking about how to integrate it in Ubricked for the simple "share high scores" case (although I really like @eievui5 idea here, maybe for a further improvement).

Maybe start the paragraph explaining sio.asm then hooking the "share high score" routine when e.g. pressing select on the game over screen?

To be honest, I don't think having an independent, standalone ROM only to showcase the serial feature is a bad idea, so I'd merge that as well.

@avivace avivace requested a review from ISSOtm August 23, 2024 17:38
@avivace
Copy link
Member

avivace commented Apr 2, 2025

Hey @quinnyo do you have any news on this?

@avivace avivace requested review from AntonioND and removed request for ISSOtm and Rangi42 April 2, 2025 11:57
@quinnyo
Copy link
Contributor Author

quinnyo commented Apr 3, 2025

Hi!

I just lost my momentum on it towards the end of last year, when life things happened.
Things are relatively stable now, so I can probably start getting back to it.

@avivace
Copy link
Member

avivace commented Apr 4, 2025

@quinnyo thanks a lot!

Also, since we did put bounties on this issues, if you give us an email address (you can DM me that on Discord or to 'gbcompo' at 'gbdev.io') I can send you an OpenCollective invitation to claim those $ bounties :D

@quinnyo

This comment was marked as outdated.

@quinnyo
Copy link
Contributor Author

quinnyo commented May 16, 2025

OK so I implemented something in unbricked, which seemed to make more sense than continuing with the demo/test tool.
The tool was really for me to develop the thing and for others to test it, anyway. With that in mind, I kept the code, but moved it to a separate file.
Anyway the feature is "score sharing" -- but it's the current score, so it's a little bit similar to how Tetris worked.
The lesson text will obviously need to be brought up to speed but I'll work on that once someone's looked at the code.

Oh, and just a note to anyone testing this: if you're using Emulicious, expect trouble -- its serial emulation is a bit weird and introduces problems that don't happen on real hardware. GBE+ serial seems good but it's a bit lacking in other areas.

@avivace avivace requested a review from ISSOtm May 26, 2025 19:45
@avivace
Copy link
Member

avivace commented Oct 31, 2025

@quinnyo I see this is still in 'Draft'. Would you consider this merge-able now? or what's missing for you that you would still like to add?

I guess we "only" miss the lesson text to accompany the code?

@avivace avivace removed the request for review from ISSOtm October 31, 2025 14:41
@quinnyo
Copy link
Contributor Author

quinnyo commented Nov 1, 2025

I'll take the PR off of 'draft' status, I didn't have any strong intention to leave it on after the last update. Apologies if it being marked as a draft was holding things up or sending the wrong message.

The code is done, I have no changes planned. Of course, I'll be happy to fix any issues that come up.

  • It needs to be reviewed.
  • Someone other than me should probably test that the feature actually works.

The lesson text needs work, but I'm reluctant to forge ahead with that without knowing that the implementation is locked in.

  • From memory (can't check right now) many of the transcluded code snippets were broken, after making changes to the code.
  • The sections toward the end on integrating Sio, the protocol and handshake stuff (i.e. the code in main.asm) are not in sync with the unbricked based implementation.
    • The current implementation (& how it's integrated in unbricked) is pretty simple compared to what the lesson is referring to -- so I'm expecting a fair bit of that text can be cut.
  • The rest of the text is more general or about code in sio.asm -- most of this should be OK.
    • there may be some slight discrepancies with the code
  • There's some WIP notes & TODOs throughout.

@quinnyo quinnyo marked this pull request as ready for review November 1, 2025 08:44
Copy link
Member

@avivace avivace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, great work @quinnyo ! I'm starting a thorough review of the text and it reads amazingly.


Before we can transfer any data, we need to configure the *clock source* of both Game Boys.
To synchronise the two devices, one Game Boy must provide the clock signal that both will use.
Setting bit 0 of the **Serial Control** register (`SC`) enables the Game Boy's *internal* serial clock, and makes it the clock provider.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other Game Boy must have its clock source set to *external* (`SC` bit 0 cleared).
The externally clocked Game Boy will receive the clock signal via the link cable.

Before a transfer, the data to transmit is loaded into the **Serial Buffer** register (`SB`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first byte to send is loaded from `wSioBufferTx` before a jump to the next function starts the first transfer immediately.

<!-- PortStart -->
Activating the serial port is a simple matter of setting bit 7 of `rSC`, but we need to do a couple of other things at the same time, so add a function to bundle it all together:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I missing something or this is being called rSC now? but was SC? https://gbdev.io/pandocs/Serial_Data_Transfer_(Link_Cable).html#ff02--sc-serial-transfer-control

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All MMIO register names in hardware.inc are prefixed with r to distinguish them from ROM, SRAM, WRAM, and HRAM labels. See "ASM style guide".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pinobatch thanks Pino. It's just that in other parts of the document it's called SC, so seeing it as rSC after a point may be confusing, so I'd suggest sticking to one name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was deliberate, but it may be needlessly confusing. It's rSC (with the r) here because it's talking about concrete implementation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@quinnyo can we try to make it a more deliberate? E.g. make it explicit when the shift to rSC happens?


:::

To check if the internal clock is enabled, read the serial port control register (`rSC`) and check if the clock source bit is set.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as previous, regarding rSC.

@avivace avivace self-requested a review January 3, 2026 20:39
:::tip

The checksum implemented here has been kept very simple for this tutorial.
It's probably worth looking into better solutions for real-world projects.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know some alternatives we can suggest?

Copy link
Contributor Author

@quinnyo quinnyo Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good jumping off point to learn more would be Ben Eater's videos:

Reliable data transmission
https://www.youtube.com/watch?v=eq5YpKHXJDM

Error detection: Parity checking
https://www.youtube.com/watch?v=MgkhrBSjhag

Checksums and Hamming distance
https://www.youtube.com/watch?v=ppU41c15Xho

How do CRCs work?
https://www.youtube.com/watch?v=izG7qT0EpBw

A proper and complete explanation of this is beyond the scope of this lesson.
You can continue the lesson understanding that:
- This is the serial interrupt handler. It gets called automatically after each serial transfer.
- The relevant stuff is in `SioPortEnd` but it's necessary to jump through some hoops to call it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"relevant stuff" here feels a bit confusing

Copy link
Member

@avivace avivace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing: build script for the new CI/CD

avivace and others added 4 commits January 6, 2026 00:37
Co-authored-by: Antonio Vivace <avivace4@gmail.com>
Co-authored-by: Antonio Vivace <avivace4@gmail.com>
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.

Serial Transfer to share High Scores in Part 2

3 participants