Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
1

Joining Toastmasters in Japan to Make Friends

from TokyoDev [alt+shift+b] in programming

“Find a hobby or join a group so you can make friends.” That’s one of the most common pieces of advice people give when you’re wondering how to meet new people, and I decided to take it. I had just moved to Fukuoka after my job hunt as a post-graduate and a friend introduced me to the local Toastmasters Club. I joined in 2020 and remained a member until 2022. Although I knew almost nothing about the organization, I saw it as an opportunity to expand my social circle. I had no idea that what began as a simple search for friendship would introduce me to such a unique community, one where people of different ages, backgrounds, and nationalities could connect beyond Japan’s usual social boundaries. What is Toastmasters, and why is it popular in Japan? How does Toastmasters work? What was Fukuoka’s Toastmaster Club like? Two years of Toastmasters What is Toastmasters, and why is it popular in Japan? Toastmasters is an international nonprofit organization that helps people develop their public speaking, communication, and leadership skills. It was founded at a YMCA in California in 1924 before gradually expanding around the world. What surprised me was Toastmasters’ history in Japan. The first clubs in Japan were established in both Tokyo and Fukuoka after World War II. Initially, membership was limited to U.S. military personnel stationed on American bases. But over time, the organization expanded beyond the military community. It originally started as a men-only organization, with women not being admitted until 1973. Living in Fukuoka, I found it fascinating that the organization’s roots were closely tied to both the city and the postwar U.S. military presence. Because I grew up on U.S. military bases across Japan, discovering this connection made me feel more comfortable joining. How does Toastmasters work? Fukuoka Toastmasters Club followed the standard Toastmasters format: we met every two weeks at the AIREF Building in Fukuoka; each meeting had a theme, and every...
3rd Aug 2026

Stay updated

Get a weekly newsletter with the top 5 articles worth reading every week.

More from TokyoDev

How I Got a Junior Software Engineering Job in Japan From Overseas

Many people say that to find a software engineering job in Japan, you need to be here first. The most common ways into Japan without a job are to become a student, arrive on a Working Holiday visa, or use the J-Find visa — all of which mean spending a lot of money just to show up and still not be sure it will work out. When I was a university student in India, I knew very well that getting hired as a junior software engineer in Japan while still overseas would be difficult. It makes sense, as companies here hire on trust, and trust is hard to build at a distance. But Japan is also a country staring down a shortage of hundreds of thousands of IT workers by 2030, with foreign workers already at a record 2.6 million and still climbing. The door is harder to get through, but there’s a whole line of people worldwide standing in front of it, and the country actually needs them to come in. Now I’m a tech lead at a Japanese startup, where we help people find and buy abandoned homes (空き家, akiya), which made up a record nine million properties in the government’s 2023 survey. I’ve lived in Japan for just over a year. I know there are a lot of people out there chasing the same Japan dream, working hard for it just like I was a few years ago, so I hope they can get a few ideas from someone who has already done it. How I got hired as a junior software engineer from overseas What I’ve learned working as a software engineer in Japan How to get a junior software engineering job in Japan Conclusion How I got hired as a junior software engineer from overseas I came to Japan despite many hurdles. Let me lay out everything that happened, and everything I did, to close the gap between me and what I wanted My starting point I started a four-year computer science degree in 2020, and it was the first time I was studying something I actually cared about. My grades sat around 8.9 out of 10 each semester and it barely felt like work. That taught me something I still believe, which is that the hard part is never the studying, it is finding the things worth studying. For me, one of those things was Japan. I’d trained in karate back in India up to green belt, and that pulled me towards the culture. I soon found I also loved the food, the nature, and the level of hospitality. So I set a goal: get my first job in Japan within three years. I also knew the usual route to Japan my classmates took—the mass campus placements, with hundreds hired in one batch—wasn’t for me. I didn’t think I was above it, but I could easily see myself disappearing into the crowd. Instead, I went looking for another way in. Finding a door to Japan What I needed was a connection, a thread that could somehow link me from South Asia to Japan. I started finding LinkedIn groups that let you work as an intern at Japanese startups. These startups were usually run by big players in Japan, often international residents, who could be the CEO or founder of many smaller companies. These are the English-friendly ones I joined back in the day: Internship opportunities in Japan Internship Japan Business in Japan They’re all pretty slow now, but in 2021 they were bustling, almost crazy with activity. The first two are internship-focused ones: students post their skills and resume, and managers share openings you can apply to directly. The Business in Japan group is different, and more of an entrepreneur crowd, but I joined it because those are exactly the people who can hire you. The one that worked best for me was Internship opportunities in Japan, because that’s where I found my first connection. I strongly recommend that group to anyone wanting an internship. Whether they start paying you depends on the company, what stage they’re at, and how much trust you’ve built with them. Preparing for a Japanese internship When I joined the groups, my resume was super odd, and I couldn’t have gotten a job or an internship with it. Still, I joined and added my Japanese-style self introduction in English. After a few days, one of the group admins messaged me about whether I wanted an internship, and then asked for my resume. It was really bad, but I sent it anyway, and we came to the mutual conclusion that I could come back later with a better skillset. Later that year I started building my skillset on my own. Honestly, you have to be a few steps ahead of your university, since they won’t teach you exactly what you will end up building at a company. At that time most people I knew went the Data Structures and Algorithms (DSA) route, which means you grind a lot of DSA, crack the interview, and figure out real building later. I went a different way. I started with learning how design actually works, and it turned out to be less difficult than it was time-consuming: you have to build a real taste for what goes where and what pairs with what. You can’t slap a Roboto font on an established news site. That went into my portfolio, which I started early and have rebuilt many times. Alongside it I shipped small personal projects to make life easier for me and the people around me, because even a silly MBTI test you play with friends is a real product if you know what you’re building. I also joined online hackathons (my mailbox was always full of stickers from them). My first real shot at a job in Japan About eight months later I went back to the admin of the internship group with these new experiences, and this time I got the chance to work with a few people from Japan Travel. The CEO of Japan Travel, Terrie Lloyd, is also the founder of Daijob, one of the country’s most well-known job platforms. Lloyd’s a Kiwi entrepreneur who landed in Japan back in 1983 on a Working Holiday visa, at 24 years old, with no degree and no Japanese, and still went on to build company after company. I was getting my chance from someone whose own story was proof that an “impossible” path was possible. We were building an idea called O2O Stays, basically a marketplace for accommodation nights. Hosts could sell nights in bulk upfront at a discount, and buyers could use them, resell them, or trade them—kind of like the short-term rentals you already know, but more flexible. I took it even though it was unpaid, for a simple reason: I had never worked at a real technical firm, and this looked like no risk and high reward. You can teach yourself to build websites, but the things that actually matter—like system design, Core Web Vitals, and the real-world problems you encounter—you only learn once actual people start using what you built. That was worth more to me than getting paid right away. My task was to build an informational website. This honestly felt huge to me back then. It was also my first real deadline and I underestimated it. The timeline slipped more than I wanted, but I was lucky to be on a team with genuinely good people, so we figured it out and shipped it. At the end I got my first letter of recommendation from my Internship, and that one letter opened the door to multiple internships after it. Building while learning A lot of that early internship experience was unpaid, and I was fine with that, because when you have no track record, even the experience itself is worth a lot. But then things started to change. In my third year at university, one of the best places I worked with was MarkoKnow, a Delhi-based startup. That’s where I built my first real application and a few admin pages, and gained a lot of firsthand knowledge. By the end I felt like I could build anything (though that was probably just the adrenaline rush). Those experiences made me want to learn more, about whatever I could do with just me and my laptop. I put a lot of time into researching Web3 and even built a project out of it that got published on IEEE with one of my university classmates. I dabbled in VR, AR, and IoT too, but the one that mattered most in the long run was machine learning, which would end up helping me a lot further down the line. I also made sure to stay in touch with people I’d met during my internships. I sent them updates on what I was building, shared my portfolio and resume each time they got better, took genuine interest in the work their companies were doing and where tech could push it further, and stayed visible by commenting on posts and checking in. Turning a connection into a job at AKIYA2.0 By August 2023 I was 20 years old, my final year of university was approaching, and my main motivation was to get a job fast. The usual path would have been an internship that converts into a pre-placement offer, and landing one in my home country is a real achievement. But the thing was, I still wanted to be in Japan. I went back to the connection I’d kept warm and asked for a new opportunity. That follow-through was what kept the door open, and this time it opened onto a great one: Terrie was on the verge of co-founding another company. It had something to do with abandoned homes, and they were offering a paid part-time job. My first task was to understand the abandoned home market and build a small scraper for a single municipality, using Tesseract OCR to read through documents, since AI still had a really bad name back then. It wasn’t pretty: on that early setup, our scraping accuracy sat around 60-70%, and validation was lower still. Later we migrated the whole thing to Gemini, which pushed scraping close to 99.5% and cut our costs by around 96%. I loved the work, and almost without noticing I drifted into much more than just software engineering. Being at a startup, I was soon hiring interns and part-timers, leading projects, and building new services and tools on my own so that nobody had to manage the extra pieces I was adding. By the time they brought me on as a full-time software engineer in March 2024, the title just formalized what I was already doing. Finally, Japan I’d just graduated that spring, and I wanted to spend a year living with my family, since I’d spent most of my life in other cities at boarding school, hostels, and university. The job with AKIYA2.0 allowed international remote work, so I had the option to stay home with my family for a year, and that was something I didn’t want to skip. Then, in April 2025, I finally moved to Japan. The move itself was surprisingly simple, because my company handled most of the paperwork. I just sent over some documents and they filed for my Certificate of Eligibility (COE). It took exactly two months, and it arrived on my birthday, while I happened to be in Singapore. I had to return to India to get the visa process started. It went smoothly and I got a three-year Engineer/Specialist in Humanities/International Services visa. What I’ve learned working as a software engineer in Japan In my three years at AKIYA2.0 so far, I’ve built three websites: https://www.akiya2.com/ https://www.singchamjapan.org/ https://www.hinokistays.com/ I also built an AI scraper covering all 47 prefectures in Japan, and became genuinely good at SEO, GEO, and system design, while managing a bunch of interns and part-time engineers. And I’m still chasing more—I want to be great at all of it. ^The mindset that got me here is simple: don’t think only about survival. Think about making your presence so bright that it becomes hard to ignore you. That mindset still matters after you arrive, because moving to Japan doesn’t make everyday problems disappear. You still have to build a life here, and how difficult that feels depends a lot on who you are and what you’re used to. For a lot of people, that adjustment is the hardest part, sometimes even harder than landing the job in the first place. The daily friction adds up in ways you don’t expect. You might have dietary restrictions, feel suffocated on a rush-hour train, spend the entire weekend recovering from the working week, or simply feel lonely. For me, the adjustment wasn’t especially difficult. I had always wanted to live independently, and after years in boarding school and hostels, I was used to being away from home. What Japan unexpectedly gave me was a real sense of freedom, because I could work during the week and travel on the weekends. That has honestly been the best part of my experience, particularly the peaceful countryside, beautiful nature, and countless shrines I’ve come across along the way. If I had the chance to start again, I would get properly good at Japanese before moving. Living here without it is possible, but knowing the language opens up far more of the country: events, friendships, relationships, jobs, and the connections that might eventually lead to a startup opportunity or even a course at a Japanese university. When you’re already living in Japan, it feels like a shame to miss so much of what is happening around you. How to get a junior software engineering job in Japan Where to find junior software engineering jobs in Japan from overseas In my experience there are two kinds of people who don’t make it: the ones who never get an opportunity, and the ones who get one but give up. The ones not getting opportunities are usually just not searching in the right places, or not building a network. How do you find opportunities? You look for them online and in communities. TokyoDev lists junior developer jobs, and is one of the best examples of how much networking matters in this career, and LinkedIn is a great tool too, if you learn how to use it. There are CEOs, CTOs, and COOs from startups and big firms sitting right there on LinkedIn and X. So what’s stopping you from a cold email? Build a portfolio that gets you noticed But a tool only gets you in front of people; after that you have to impress them. As a software engineer, the only real way to impress someone is by building something for them. And to earn that chance, you first have to get good at the basics. ^About 95% of what companies build isn’t niche or original. It’s the same kind of product that already exists across many businesses, and often in open source too. Only a small slice, maybe 5%, is truly novel. Don’t run for that 5% yet, not while you’re starting out. Get genuinely good at the 95% first, because that’s what almost every real job actually involves. After all, working in Japan isn’t niche either. The competition is huge, and being a real professional is what sets you apart. Being a professional shows in the specifics. If you’re a frontend engineer, don’t tell me you know React or Vue, middle schoolers know them by now. Show me the components you built that made your own life easier, your page load times, your Core Web Vitals, and how your SEO holds up. If you’re a backend engineer, talk about the choices you’d make for a given product, the alternatives you actually know, how you cut costs, and how you fill the gap between a developer who just writes code and an engineer who takes responsibility. That attitude is exactly what I look for when I interview interns, part-timers, or engineers. Learn what software engineering skills are in demand in Japan Another tip is to study your market and see what’s booming right now. AI is the obvious hot topic, and Japan is pouring serious money into it lately. The government has committed over 10 trillion yen (around 65 billion US dollars) in public support for AI and semiconductors through 2030, and for the coming fiscal year it nearly quadrupled its chip and AI budget to about 1.23 trillion yen (7.9 billion dollars). AI startups often get founded by certain kinds of people—Japanese citizens returning from abroad, PhD holders from Todai or Waseda, and sometimes international residents as well. Sakana AI is a good example, founded by David Ha, Llion Jones, and Ren Ito. Some of these companies even have English-speaking roles. Conclusion So target thriving sectors like AI, but keep a backup plan. And seriously, start studying Japanese, because looking at the market now it matters more and more. However, I moved to Japan in April 2025 with no Japanese at all, so there’s always a way. Don’t lose hope. If you have the right mindset, can find the places where opportunities live, and are as persistent as you possibly can be, then with time you’ll look up and realize you already have everything you were chasing. Honestly, if I can do it, I’m sure anyone reading this can too, so keep trying.

a week ago • 1 votes
Being the CTO and on the Board of Directors

July 1, 2026 marked my seventh year in Japan. Relocating to the other side of the world was not my original plan, but somehow I ended up here. I came to fill in a high management role at an AI startup, and within a few years was appointed CTO, and then a member of the Board of Directors. When I arrived, the startup was around 10 people in total. When I left, the total headcount was around 100, and I had 15 direct reports (at peak) and overall responsibility for 70 employees in the engineering department. I would have never imagined managing so many people, much less in such a high position, and even less in Japan, but somehow that is my story. In this article, I’ll give you an honest recount of my experience as CTO and member of the Board of Directors in a Japanese company, especially filling both roles at the same time. Before we delve into the story itself, I want to make it explicitly clear that all opinions expressed here are my own, and in no way do they represent my previous employer(s). This is simply my personal experience, which can hopefully be useful to someone else. CTO vs. Director The transition process Role differences and conflicts Practical advice CTO vs. Director “So what’s a CTO, anyway? What does a CTO do?” This is an actual question that I asked my CEO when he decided to appoint me to the role. Of course, I had researched online, but I wanted to know what the company needed me to do. And the answer that I got was very clear. We had three executives, so the roles were split as follows: The Chief Executive Officer (CEO) is the one who sets the global direction and vision of the company: “We will be in this position in three years.” The Chief Operations Officer (COO) is the one who will do the big picture scheduling and planning, breaking down the direction into milestones and preparing the business strategy so that the company hits these milestones. The Chief Technology Officer (CTO) is the one who takes the plan from the CEO and COO, and implements the technology to ensure the milestones are hit on time. In theory, that’s a very reasonable separation of responsibilities. In practice, things worked differently, which is natural in a startup. Becoming the CTO Different people have different opinions of the CTO role, but I’ve always thought of myself as a glorified engineer with a shiny business card. I’ve always been excited to get my hands dirty in research and coding, so doing whatever needs to be done is my natural state. The title gave me the authority to make decisions, which simply meant that if something went wrong the responsibility was mine. I was happy to take on this responsibility, as it meant that my team was protected, both internally and externally. So as CTO, in practice, I felt like I was in a position not only to lead my team, but also to protect them, support them in their growth, and ensure their comfort and safety. Becoming a member of the Board of Directors A director (取締役, torishimariyaku), on the other side, has quite a different type of role. I became a director because the company was preparing for its Initial Public Offering (IPO), and one of the requirements is that the company must have a Board of Directors. I was offered one of the five seats, and I decided to take it. The decision to accept the position seemed like a natural progression of the company’s path to IPO, and a way to formalize my role in that progression. Frankly, I was not entirely aware of the potentially conflicting responsibilities of a CTO and a member of the Board of Directors, which is one of my main reasons for writing this article. The main responsibility of a director is to shareholders and investors, and their aim is to steer the company’s direction to make it profitable. Directors are also personally responsible for the public conduct of the company. As a director, I was able to establish more company rules, such as: Setting up concrete roles with titles and responsibilities Founding an Information Security Management System (ISMS) initiative Creating new departments within the company Building an Objectives and Key Results (OKR) system from the ground up I was also able to lay down the groundwork for the future IPO of the company, and set up processes that were ultimately in favor of both the company and its employees. Employee or not? One of the biggest differences is that a director is not an employee of the company, while a CTO is. The CTO is protected by labour law rules: they have fixed working hours, vacation days, and so on, as any other employee. The CTO is part of the company’s organization chart, at the top of the engineering division, and they have authority and decision-making power within the company. But a director has no fixed working time, vacation days, or protection under labour law. In fact, a director may be dismissed from their duties if stakeholders vote them out. A director need not be an executive of the company. In my case, since as a CTO I was already an executive, my contract had to be modified; the company and I decided to sign a legal agreement that made me a fiduciary for the company. To put it simply, this designation means that the company legally entrusts directors to work in its best interest, instead of being told what to do. Since it’s not possible to be an employee and fiduciary at the same time, the company and I signed a delegation agreement (委任契約, i-nin keiyaku), which replaced my employment contract. It’s quite a standard process for designated directors in Japan. The transition process No fixed work hours The biggest practical change for me when I transitioned from just being the CTO to also being a director was the fact that I had no fixed working time anymore. Initially it felt like that was a good thing, and the extra flexibility was certainly appreciated. However, this extra flexibility came with direct accountability to investors and other board members, which in turn also meant that weekends and national holidays were not sacred anymore. Of course, there was no one looking over my shoulder, prodding me to do more, but my self-imposed internal monitor was arguably harsher than any external expectation. No visa impact Another surprising practical aspect was that I did not need to change my visa to become a director. I was on a Highly-Skilled Professional (HSP) visa at the time. The company simply registered me as a director, and for the Immigration Bureau that fact did not matter at all. I later applied for Permanent Residence (which I now possess), and again, being a director had no impact at all. I applied under the points system, so my salary was the only factor tangentially related to being a director. Changes in salary On the topic of salary, the process for salary adjustment and bonus allocation is different when it comes to employees and directors. For employees, executives propose salary adjustments, bonus allocations, promotions, demotions, and other HR-related topics for their own departments, including themselves. An executive’s salary is decided in the same way as for other employees; it’s based on the company’s salary table, and usually requires no approval by the Board of Directors. Directors, however, may propose their own salary and bonus, within a total ceiling set by the shareholders. Each proposal must be accompanied by proof of their claims of performance, achieved goals, and increased ROI. The director salary proposals are always subject to voting, so the other directors may approve or refute either the salary modification and/or the bonus. Regarding taxation, my actual salary was treated in the exact same way. I paid my taxes according to my salary bracket, not based on my title. That being said, there are some tax-related differences for employees and directors. For example, directors’ salaries must be decided within the first three months of the fiscal year, and remain fixed throughout the fiscal year. Moreover, the amount and payment date of bonuses for directors must be communicated to the tax authorities in advance, and must be paid in full on the exact day; otherwise, they are not paid at all. Another point is that directors are excluded completely from unemployment insurance, which means that if a director is voted out, they can’t claim unemployment. My understanding is that the same logic extends to parental leave benefits, since they are handled through the same contributions system; however, I don’t really have any experience with this, since my son was born while I was still only a CTO. Conflict in responsibilities The transition from CTO to director for me was gradual, so the mental shift also happened gradually. Perhaps it never happened fully, in fact. Switching from being on the employee side to being on the corporate side is not something that can happen overnight, and, quite frankly, it was a source of internal turmoil. The two roles are intended to be in tension, and one person fulfilling both at the same time can be uncomfortable. I found it challenging at times to reconcile the interest of the company and the interest of employees. Fundamentally, these interests should align, but in practice there are some tough calls to be made. I’ve personally found that the only way to maintain my sanity is to stay true to my core values and humanity, accepting that this means “failing” in certain corporate aspects. Concretely, I’ve always prioritized sincere human connection over everything else, which is why my team trusted me. So when a call had to be made, I would put myself in the place of the other person: what if I was on the receiving end of this decision? Of course, different people have different reactions, but that has been a pretty solid guideline overall. In certain situations this mentality led the CTO-me to create complications for the director-me, but in the end what counted most for my mental health was knowing that I did my best in the way that mattered to me. Role differences and conflicts As the CTO of a startup, I was used to making decisions fast, with limited information, and pivoting frequently based on the latest events. As a director, though, any decision took at least a month, because it had to be presented as a resolution for voting, and that was the cadence with which we were having board meetings. Every proposal came with a clear presentation of the rationale, the impact, and the implementation plan. After discussion with the other directors and addressing their questions, we would all cast our vote on the proposal. I could go ahead with the implementation of a proposal only after it was approved. There were good and annoying points about both methods. The CTO has more freedom, but moving too fast in a vacuum can introduce confusion, while the director must act more slowly, but all decisions are discussed and voted on, so there is no (or at least less) confusion. To give a more concrete picture of the differences between the roles of CTO and director, it might be best to share examples. Deciding pay As CTO, one of my duties was to evaluate performance, decide on salary modifications, and allocate bonuses to members of my department. I wanted to reward my team for their effort, growth, and individual contributions. As a director, though, I had to ensure that this process was transparent, auditable, and fair to everyone. This meant I had to establish a formal procedure that was voted on and approved by the Board, and was then implemented gradually with some limitations. Most limitations come from the legal aspect of the director role: changes are best rolled out slowly, by introducing small pieces as we verify that the base system works. Unfortunately my full-fledged RPG-based career advancement framework disguised as OKRs was initially refused. However, I did eventually get a functioning system up and running. Tracking attendance Another example was when I implemented an internal attendance tracking system. As CTO, I was aware of the progress done on all projects, and I was happy to keep bureaucracy to a minimum and focus on getting things done. That had been the basis of our flexibility and “getting things done” attitude since I’d started with the company. As a director, however, I had to provide auditable data on our projects. What this meant was that I had to provide a monthly, and possibly even weekly or daily, breakdown of how much time every person had spent on every project, then connect that information with the revenue from the specific projects and compile a detailed report on Return on Investment (ROI). The challenge for me was finding a way to track this data without invading people’s work to the point where it became disruptive. It took some creativity, and for me the focus was to integrate this attendance management system into the tools we were already using on a daily basis. In the end, I managed to build something functional, but the main problem was, and will always be, data integrity—a story for another time. Introducing order in chaos When I joined the company, the organization was flat, but as more and more people started to join, at some point we needed specific roles, responsibilities, and designated titles, so that people knew who to refer to. As CTO, I knew the strengths and weaknesses of every single person on my team, and I was freely delegating tasks to the ones that I knew wanted to expand in certain areas and would be able to meet the expectations of the projects. I was not afraid to give people room for growth, and in fact I was frequently amazed by the leaps some of my teammates would make. As a director, on the other hand, I had to break the flat organization into a department organization chart, assign titles and roles to people, and even establish new departments within the company. The process of deciding on the titles and the responsibilities associated with each was non-trivial, especially if people were involved in multiple projects. Ultimately, this process evolved into a project management framework in which a team was formed at the beginning of the project. Members were assigned to specific roles for a given duration, and we laid out their expected involvement with measurable deliverables. All this was quite different from the ad-hoc project work I was used to in the early days. Practical advice In this final section, I’ll try to distill some advice. I don’t know what may apply to you in particular, but I hope some of these will resonate. As an employee As an employee, you should keep in mind that your CTO is also an employee, and the same rules and laws apply to them, both as a protection and as a limitation. Being an employee, the CTO is more likely to be on your side, keeping in mind that their mission is to guarantee the success of the company from the technology point of view. A director, on the other hand, is not an employee, and they have an obligation to make the company profitable. This distinction might be rather subtle, but keeping it in mind can make it clearer how much freedom and capacity each of these roles holds to advocate for you, and how much personal risk that carries for them. Another point to be mindful of is that your salary and bonus might be decided or at least approved by the CTO. Some companies have HR departments dealing with salaries, but in my experience, even if the information runs through your manager or department head, there is a high chance the CTO will review all salaries before they are presented to the other executives, or to the Board of Directors. Presenting your progress, impact, and growth in a language that the CTO understands can only be in your favor. Talk in terms of ROI when negotiating salary increases, bonuses, and promotions. It’s very helpful for you, your manager, and your CTO, and it increases your chances of reaching your target. For future CTOs and directors If you’re on track to become a CTO or a director (or both!), the most important advice I can give you is to figure out your role before you are forced to. As a CTO you protect your team, while as a director you’re accountable to shareholders. When there are conflicts of interest—and believe me, there will be—you must have a clear idea of where your priorities lie. ^Making a decision as a director and telling yourself that this is the right call as CTO, or the opposite, is not necessarily always true. Make a clear distinction of which role you are embodying with each decision, and be able to defend it in front of your team and the Board of Directors. Maintain your mental health Finding yourself in a dual position with conflicting expectations can be draining, so finding a sane way to deal with such situations is a requirement, not an option. One of the best ways I have found to do that is to be consistently true to myself. Yes, there are different rules, responsibilities, and expectations for different roles; however, the one invariant is that you are the same person at all times. In the long run, staying consistent with your core principles is much more valuable and productive than constantly shifting from one personality to another. Know what you’re signing up for If you are becoming a director, be very clear about what you are giving up. I say this not to scare you off from the position, but to encourage you to be able to protect yourself legally, financially, and professionally. Giving up employment as CTO means you give up paid time off, vacation days, parental leave eligibility, and protection by labor law. It also means no fixed working time, so in theory you could be working much less, provided that you fulfill your duty to the company. Related to that last point, set your own limits as a director, because no one else is allowed to. On the flipside of hourly flexibility is overworking yourself, because there is always more to do. Before you get trapped in the vicious cycle of “just one more thing,” set safeguards to protect yourself from burnout. Don’t be afraid to try something new If you have the chance to be a director, and you are comfortable with the responsibility, go for it! It will give you a completely fresh perspective on how a company works, and you will learn many new things that can help you protect yourself, your team, and your own company. Good luck out there. Do your best, and stay true to yourself.

3rd Sep 2026 • 1 votes
Dealing with Pathological Anxiety in Japan

My honest opinion is that very few things in one’s life can be as fulfilling as living abroad. The opportunity to break away from my comfort zone, brave new horizons, and immerse myself in new cultures has probably been the greatest joy I’ve found during my time on this Earth. Japan in particular holds a deeply special place in my heart, given my long-standing love for its culture and people, both of which have been part of my life since my childhood in Brazil. Of course, that raises the question: “Well, how come you’re talking about having anxiety in Japan then?” The truth is, living abroad has brought me woes and wonders in equal measure. In Japan specifically, I found myself dealing with a worsening mental state while simultaneously experiencing a completely new environment, all with very little immediate support, given that my friends and family were, quite literally, on the other side of the world. I had to locate help on my own and deal with a medical system that was completely foreign to me, in a language I couldn’t freely communicate in. Through this article, I aim to share some of my experiences dealing with severe anxiety and navigating Japan’s medical system, in the hopes that they can, in turn, be of help to someone else. How the anxiety began Finding help (for the wrong thing) Mental health in Japan Finding help—again Bringing medicine into Japan Helping yourself Final advice Resources How the anxiety began Japan was not my first experience living abroad. Before coming here, I lived in neighbouring Taiwan for around three years. Deciding I wanted to try living somewhere else, I settled on Japan, as it seemed to have a vibrant international developer community (through TokyoDev, of course). Once the decision was made, it was time to prepare. All in all, it took me a year and a half to feel comfortable enough to make the move. However, everything did not go as smoothly as I’d hoped. There were quite a few bumps on the road, which almost made me give up on the move altogether, but in the end I decided to go through with it. Instead of finding work before the move, I chose to study the language while searching for employment. This made failure a much riskier prospect, as I was now actively investing both time and money into my stay in the country. All of this is to say that I was already under quite a bit of pressure when I arrived. Arriving in Japan with a purpose was a much different experience than when I had visited it in my travels. Here I was, in the country I had spent so long preparing for, and it was time to make it work. And I was definitely going to make it work! Looking back, this was my first mistake, since as the difficulties piled on, so did the stress. Eventually something had to give, and that thing was my stomach: unexplained nausea, digestion troubles, lack of appetite, and so on. It was quite frustrating that just a few weeks after I arrived in Japan I already found myself having to deal with health issues. Oh well, nothing to do but have it looked at, I thought to myself. Finding help (for the wrong thing) If you’re in Tokyo, you won’t have any trouble finding yourself a clinic for pretty much every specialization known to modern (and even ancient) medicine. Most of them have a listing on Google Maps, and you can usually find them just by typing the specialty in plain English. The process itself is quite simple: choose the clinic, make a reservation through their website or by phone, and show up with your insurance card (保険証, hokenshou) or My Number Card (マイナンバーカード, mainanba–ka–do). Since I was a student at the time, I was enrolled in Japan’s National Health Insurance system (国民健康保険, kokumin kenkou hoken), which meant that I only had to pay for 30% of all medical expenses. At the time, as I thought my symptoms were physical, I searched for an internal medicine clinic (内科, naika), and actually ended up finding a gastroenterologist near where I lived. However, the doctor didn’t speak English, and while some doctors in Japan do, this is by no means the norm. Finding clinics that actively cater to foreigners can be even more difficult. They certainly exist, but they also tend to have limited availability, and higher prices on average because they often don’t accept NHI. Knowing the doctor didn’t speak English meant I had some homework to do before my appointment. I researched how to describe some of my symptoms in Japanese, noted them down on my phone, and translated the rest on the go during the visit. All in all, everything went smoothly. The doctors and nurses were very kind and made sure we could fully understand each other every step of the way. After a battery of examinations, however, it was clear that there was nothing particularly wrong with my stomach, and that the problem lay elsewhere. This is where my experience started to become frustrating. Once digestive issues were ruled out, I ended up with no guidance on what to do next, and was merely given more medicine for the immediate symptoms. Feeling sick on the train? Here’s some medication for that. Dizziness? Here’s another one. When I finally connected the dots that the problem might be related to stress or anxiety, and brought it up with the doctor, I was told to “Drink some coffee every day to relax.” Mental health in Japan Historically, mental health has carried significant stigma in Japan. A 2013 study showed that “mental illness was considerably stigmatised, with schizophrenia being more stigmatised than depression” and that “the general public often lacked accurate knowledge about mental illness.” Some of the effects of this stigma can be seen in the healthcare system itself. A 2015 OECD Review pointed out that “service provision for mild-to-moderate disorders, such as depression and anxiety is poor relative to the expected burden of disease,” and that the mental health needs of vulnerable groups, including children, adolescents, and the elderly, were not being adequately met at the time. However, a more recent study from 2023 suggests that attitudes toward conditions such as depression have become more informed over time. Increased public discussion around mental health, alongside government efforts to improve awareness and access to mental healthcare, may have contributed to this shift. Finding help—again The old stigmas might, at least in part, explain the doctor’s response. Given the sensitive nature of the issue, he might have been reluctant to bring up the topic, or to address something outside his area of expertise. Whatever the reason, I once again found myself searching for help on my own. Since my mental health was a far more complex issue than my stomach pains, I decided not to compromise this time and instead looked for a professional with whom I could discuss my problems without struggling to find the right words. Even disregarding the language barrier, many of the local mental health clinics I came across during my search had surprisingly very poor reviews on places like Google Maps. The dislike seems to derive from the way the appointments are handled: people walk in, tell the doctor all their symptoms and concerns, and then get prescribed medicine without much care or thought, all in under 30 minutes. You might recognize this as a fairly common experience when seeing any doctor in Japan. While this approach might be fine when treating a rash or a cold, when it comes to people’s mental state, it leaves a lot to be desired. There are a few clinics which can properly accommodate foreigners, usually offering support in multiple languages in addition to English. With that said, I ran into two problems. First, they were often fully booked for weeks on end. Second, many of them did not accept Japan’s National Health Insurance, meaning that I would have had to pay out of pocket. Things were much the same when I looked for a therapist, as psychotherapy sessions are not covered by the NHI at all. While I did eventually find some very promising clinics by that point my symptoms threatened to overwhelm me. I was unable to ride a train, travel by car, or even sit through a 30-minute lesson without experiencing severe discomfort. My daily life had become so disrupted that even the smallest things took me a great deal of effort. Faced with this, I decided to return to my home country during the semester break in order to seek help in a more familiar environment. Bringing medicine into Japan I initially planned a short, two-week stay, but once I saw the doctor it became clear that that wouldn’t be the case. I was immediately diagnosed with anxiety disorder and agoraphobia, and started on medication. While I was relieved to finally have a proper diagnosis, I knew that the road to recovery would be a long one. It took almost two months for me to be healthy enough to face the 30-hour journey alone back to Japan. The medication also introduced a new challenge: once I left Brazil, I would have to find a way to obtain it in Japan. The first point I needed to confirm was if I would be able to fill my prescription while in the country. Since I was prescribed escitalopram, an SSRI (Selective Serotonin Reuptake Inhibitor) that is very commonly used as a treatment for depression and anxiety, I learned it was readily available at most pharmacies as long as I had the prescription on hand. This isn’t the case for all medicines, however. Some, like Bupropion, are not sold within the country, and need to be replaced by viable alternatives. Another option would be to bring them into the country by presenting an Import Confirmation Certificate (輸入確認書, yunyuu kakuninsho) upon arrival, but not every medication can be brought this way, and there are also strict limits on the amount imported per person. Many of the same restrictions apply if you plan on importing them after arrival. Depending on the medication, receiving additional supplies from a family member abroad may be difficult or even impossible. Even if your medication is sold here, you will still need to see a doctor in order to get a Japanese prescription. Most doctors will readily help you continue your treatment as long as you present proof of your diagnosis, such as previous prescriptions or a letter from your doctor, which can all be in English. They may also evaluate you before continuing treatment, at their discretion. With your prescription in hand, you can head to any pharmacy to obtain your medicine. Helping yourself Being given what was essentially a second chance to enjoy my life in Japan, I decided I would do things differently, if only to avoid falling into the same traps of the past. For me, that meant I started going to the gym, talking to a therapist, attending meetups with like-minded people, doing hikes, and etc. These are generic things, sure, but they are surprisingly effective. By keeping both mind and body busy, you avoid ruminating about the past or worrying about the future. At the same time, the meetups and hikes provided something to look forward to, a reward of sorts for the week’s efforts. Another very helpful thing was finding ways to practice my Japanese. Interacting with people, either in real life or online, can soothe the feelings of isolation so commonly felt by expats. Dating apps like Bumble are surprisingly good tools for casual conversation, even if you’re not interested in dating. In fact, I would go one step further and say that reaching out to people was the most important thing for my recovery. In the past, I felt everyone else was having the time of their lives in Japan while I, alone, was suffering through it. When I finally reached out, the amount of support and understanding I received was both comforting and surprising, but most of all it gave me the sense of belonging I so desperately needed. You will also find that the people you interact with might help you in ways you hadn’t even considered before. When I told the staff at my language school about what had happened, they were extremely helpful in finding me a clinic at which to continue my treatment. In much the same way, I later learned from an acquaintance that the Tokyo government offers a hotline specifically for introducing clinics. This article itself is a coping strategy. Putting things into writing can be a cathartic experience, regardless of whether there will be an audience for it or not. Writing will take things out of the ephemeral and force you to structure them in a way that helps ease the usual catastrophic thinking that often accompanies anxiety. And finally, even though it’s a cliché, remember you are not alone. Looking back, one of my biggest mistakes was trying to deal with everything on my own. Moving to a new country is never easy, and even the most cheerful people can be affected by it. Reach out to friends and family. There is no shame in sharing your problems and worries with those who care about you. Final advice Fighting anxiety is a long battle, and even after you believe you’ve defeated your enemy, it can return in unexpected ways. The medicine didn’t magically solve the problem, but made it considerably easier for me to tackle it on my own. Life in Japan has become better than I ever could have hoped for, and I can truly say that I’m living it to the fullest. I’ll leave some of the resources I found along the way below, in the hopes that they can be of use. Resources ABC Japan, a Brazilian NPO that offers free consultations with a therapist in various languages. I’ve used ABC Japan’s consultation services myself. While their schedules are very busy, the doctors are very patient and will listen to your troubles very carefully. A Reddit thread detailing foreigner-friendly mental health clinics in Japan Meetup.com, for finding communities with many different interests TELL Japan, a NPO which maintains a toll-free hotline in English. While I did not use TELL’s services, they’re often brought up when speaking with foreigners about mental health, and come very highly recommended. Finally, feel free to reach out to me at [email protected] with any questions you might have regarding anything in this article. I’ll be more than happy to help.

10th Jul 2026 • 2 votes
Scam applicants are an increasing problem in Japan

この記事は日本語でもお読みいただけます。 Over the last six months, TokyoDev has received a handful of reports from our clients about fraudulent applications, in which candidates purport to be different people than they actually are. As a relatively niche job board that helped Japanese companies make 93 hires last year, the overwhelming majority of our applicants are real people. Nevertheless, this trend is disturbing. All these reported scammers share one particular characteristic: they claim to be Japanese citizens living abroad, or recently returned to the country. One reason for this commonality is that our clients are actively seeking to hire more bilingual Japanese citizens, who are rather rare to begin with, so our clients are far more likely to interview these candidates than if they had claimed another, non-Japanese identity. Reports to us have mentioned that they believe these scammers are North Koreans, a possibility that has been reported elsewhere. My theory is that these scammers are actually assuming a Japanese identity in order to target American and other international companies. The typical Western person won’t be able to easily differentiate whether someone comes from Japan or North Korea based upon appearance and English accent alone. Pretending to be Japanese saves them from having to use video or audio filters during interviews. If a scammer is using an automatic tool to apply for English-speaking software jobs around the world, they may just happen to apply for one of the jobs on our site. I don’t have any reason to believe that TokyoDev and our clients are specifically being targeted. The end goal of these people is not entirely clear. At best, they want to get paid money directly. At worst, they’re performing industrial espionage or looking for opportunities to inject malware into their target’s network. Regardless, even if they’re all caught, the time they waste and the distrust they sow is incredibly harmful. In this article, I’ll outline what I’ve witnessed and the measures we’ve taken so far. By compiling the signals we’ve seen, and our best techniques for catching scammers, we can hopefully stop companies who use TokyoDev (and even those who don’t) from actually hiring these candidates. Attributes of a scammer Besides claiming to be a Japanese citizen, these are other attributes common among scammers applying via TokyoDev. While these don’t guarantee that someone is a scammer, if an applicant has any of them, proceed with caution. Resident of Japan with a US phone number It is easy and cheap for anyone in the world to get a virtual US phone number, and use VoIP to answer it. This makes the numbers attractive to scammers, as they can say they’re based in the US and have a legitimate-looking phone number to prove it. I’ve frequently seen scammers say they’re currently in Japan, but list a US phone number. While I suppose it is possible for someone to be a resident who has only recently relocated to Japan and not have gotten a local phone number, the chances of this are quite slim. Non-existent Japanese phone number The Japanese government places restrictions on who can get a phone number. To get a virtual phone number, you need to be a resident of Japan. Non-residents are able to get a Japanese voice SIM, but they must physically be in Japan to receive it and present ID when doing so. While there is a black market to get around this, using it increases the cost and risk. Likely because of this, I’ve seen cases of scammers putting fake Japanese phone numbers on their resumes. If someone calls the number, the game will be up, so I guess they’re just counting on it never being called. Senior candidate with a generic portfolio website Scammers are usually trying to appear quite senior, with eight or more years of experience. Some of them will provide a link to a “portfolio” website, often hosted on a subdomain of a free hosting service, such as GitHub pages. The website usually feels very generic and just lists their skills and projects. It doesn’t have any unique content, like a blog. I’ve seen legitimate junior candidates create something like this, but good senior candidates won’t waste their time. If they have any website at all, the most they’ll do to sell themselves is post a link to their resume. Worked at famous companies, but most recent one is “anonymous” or “stealth” I’ve seen scammers who will say they previously worked for famous big tech companies, such as Amazon, Google or Meta, but list their most recent employer as “anonymous.” I suppose they’re doing this to strike a balance between creating an attractive profile, and being able to withstand basic scrutiny. However, legitimate candidates will normally list who their current employer is. I know of one scammer on TokyoDev who tried this tactic out, but later moved on to listing minor companies instead, perhaps because he realized pretending to be ex-FAANG made him too obvious. What doesn’t work to catch them Here are some techniques we’ve investigated that initially seemed promising, but won’t consistently catch scammers. IP address-based detection Some applications from candidates that claim they’re based in Japan do have non-Japanese IP addresses, but many fraudulent candidates also will have Japanese ones. Furthermore, those addresses often can’t be caught by VPN detectors; it appears that they are using residential Japanese ISPs. There are less ethical services that will provide you with a residential proxy, so it seems that these candidates have clued in and started using them. Listing your job as “partially remote” or “no remote” Even though these fraudulent candidates are based outside of Japan, I’ve still observed them applying for jobs that require candidates to come into the office. From talking to our clients, it seems like these candidates have a story about a sick relative or injury that they’ll use as an excuse for why they can’t come into the office initially. What can catch them While I can’t guarantee that these measures will continue to work, right now they seem the most promising. Ask for a Japanese phone number Virtually every resident of Japan has a Japanese phone number, so when screening candidates who claim to be in Japan, you can call the number they list or ask them to provide one if they don’t. For extra certainty, call the number while on a video call so you can confirm the person you’re interviewing is the one answering it. While not foolproof, from what we’ve observed, this is enough to stop at least some scammers. Screen in both English and Japanese Scammers sometimes pretend to be Japanese citizens to mask the fact that they speak English with an accent. This can be their undoing, though, as while they may be prepared to interview in English, it is unlikely that they can speak Japanese at a native level. By screening candidates in both languages, you may be able to identify that their language ability doesn’t match their assumed background. Clients have reported that when they switch from speaking English to Japanese, scammers often just drop out of the call. Use an identity verification service It’s quite common these days, when signing up for apps that involve financial transactions, to perform some type of identity verification, where you upload your ID and also go through a facial recognition process to ensure your ID matches. While it would be too expensive and invasive to ask all candidates to go through such a process, I think it is reasonable to have candidates do this before you onboard them, especially if you’re hiring someone to work fully remotely without ever meeting them in person. Perform onboarding in-person If a scammer outside of Japan somehow makes it through your whole interview process, they’re only going to start working with you if they can work completely remotely from day one. Even if your company works fully remotely, completing onboarding in person will most likely catch them. Travelling to Japan may be impossible for scammers, both from a financial perspective, and because they may not even be able to secure a visa to travel here. Use an ATS with built-in fraud protection I’ve observed that some Applicant Tracking Systems (ATS) are starting to offer fraud protection. I have similar qualms about this as using AI for screening, since legitimate candidates are unfairly going to be skipped over. At the same time, ATS are the only ones in a position to solve this problem at scale. When you’re processing millions of job applications per month, the patterns of scammers become a lot more obvious. If you’re already using an ATS provider, talk to them about how they can help prevent applicant fraud. Take note of how exactly they’re doing it, and make sure you also understand what sort of legitimate applications will be screened out by them. What is TokyoDev doing about scammers? As a job board, we’re in a bit of an awkward situation. On the one hand, we don’t want to be the source of scam job applications. On the other, we have a duty to uphold the privacy of our applicants, and also must follow Japanese regulatory requirements that prevent us from screening candidates. If a company reports to us that they believe a job application is from a scammer, and the candidate applied via TokyoDev’s own job application form, we mark that application as fraudulent. If we receive a similar job application in the future, we flag it for manual review, and if it seems likely the flagged job application is also a scam, we do not forward it. It’s our understanding that this is in compliance with Japan’s job board regulations. This process only catches people applying via our own job application form. As about half of our job listings direct candidates to the company’s ATS, it does nothing to prevent fraudulent applications via those systems. While we considered maintaining a list of fraudulent candidates to share with companies, we eventually dismissed this idea both because of privacy concerns, and because we think it is unlikely that companies will actually verify candidates against it. Beyond that, I think that education around this issue is what’s most likely to make an impact, which is why I’m writing this article. Conclusion I expect we’re just seeing the tip of the iceberg here, and things are going to get worse before they get better. Generative AI has been a great boon to scammers, making it easier to automate sending customized job applications as well as to pass the interviews themselves. Just like email spam was once a huge problem, and then was largely resolved, this issue will probably follow the same pattern. Right now ATS are a commodity, and there are hundreds if not thousands of options to choose from, but the prevalence of scammers could lead to a handful dominating the space. Google is able to offer some of the best spam filtering because of the huge volume of email that moves through their servers; similarly, the ATS that process the most job applications will be in the best position to detect applicant spam. I think it would be a bad thing to have a few companies serve as gatekeepers for the majority of people changing jobs, but that also is likely to be the outcome. One process that’s immune to all of this, though, is people changing jobs via in-person connections. A referral from an existing employee is almost certainly going to be a real person. This is one of the reasons TokyoDev supports our local tech community, both by holding our own events and sponsoring others. If you’re looking to hire developers, you can get involved too! You’ll be doing good as well as building up your own pipeline of candidates who are not scammers, and who already have a positive association with your brand.

3rd Jun 2026 • 1 votes

More in programming

Writing a Demoscene Intro for the ZX Spectrum

Download Now View on pouet.net Intro In the late 80s, I spent an embarrassing number of hours hunched over my ZX Spectrum, typing in Sinclair BASIC programs and rudimentary assembler routines copied from magazines, trying to re-create the Amiga crack intros I’d seen round at a friend’s house. Obviously, they never came even slightly close - but now, many decades later, I’ve finally managed it! I’m now the proud author of a hand-rolled retro demoscene intro that runs on a stock 128Kb Spectrum. It features all those late 80s tropes: A smooth scrolltext (with ‘leet custom fonts!), a three-channel AY soundtrack, bouncing VU meters and the essential parallax starfield. It’s currently 10287 bytes of code, or 19552 bytes as a complete tape image - which, given I’ve been working on this since December 13th last year, means my average rate of code-production is a paltry ~ 455 bytes per week! This blog post is a technical overview of how I got there, some cool tricks I picked up, and everything I had to learn (and re-learn) about the Speccy and Z80 assembly along the way. It simultaneously rates as one of my favourite side-projects ever, and also the one that most often nearly triggered a foot put through my monitor in frustration. I’ll reflect on all that at the end, but for now if you just want to see the finished product, the download button is at the top of the article and the included .tap cassette tape image should load into any emulator. There’s also a YouTube capture, links to the production on pouet.net, and you can run it from within a web browser by visiting my TNFS site portal - check option 4 for recent uploads. Be Kind, Rewind But let’s skip back briefly to the late 80s. Coming from the world of an 8-bit, cassette tape loading computer, seeing an Amiga for the first time was like encountering something from outer space. Like everyone who saw one back in the day, I was blown away by the amazing graphics and sound on display, not to mention the library of ground-breaking games. But I found myself even more captivated by the mysterious (and totally badass) “intros” displayed at the beginning of pirated games. Created by the software piracy groups that had cracked the copy protection and distributed the floppy-disk based games, they were mini works of art in their own right - music, graphics and usually some cool-looking effect to show off the group’s prowess. There’s a great collection of these intros (or “cracktros”) archived on YouTube. Watch a few of those videos and you’ll quickly notice the “design” tropes that almost every cracktro shares: a cool, edgy logo at the top of the screen (bonus points if it’s dripping blood or in any way “metal”), some boastful text displayed on top of an effect of some sort - usually a scrolling parallax starfield, or rotating 3d object - and a further scroll-text full of shout outs, greetings to fellow pseudonymous crackers and adverts for illegal BBS systems galore. Needless to say, to a kid in the 80s/early 90s this was possibly the coolest thing ever. I thought this one was the absolute bomb when I first saw it. Sine-scroller, pirate BBS adverts, cool logo with a sword - and of course, a starfield. There’s something for everyone here. The music from this is burned into my brain. I think pretty much everyone of my classmates knew this intro given the popularity of Lemmings in the early 90s. Skid Row as a group are still active to this day and this is probably the quintessential Amiga cracktro of the period. Endless Piracy. Edgy. Another cool logo, sine-wave scroller, starfield and boasting text. The classics never go out of style. Another great combination of all the essential ingredients. Cool logo, even cooler text font, scrolling starfield and a scroll-text running along the bottom. Vintage stuff. Logo. Text. Scroller. But no starfield - otherwise a solid effort from Anthrox here :) The demoscene grew out of these intros. The cracking eventually faded into the background, and coders, “graphicians” and musicians all contributed to feature-length productions that showcased their abilities, competed with other groups and pushed the machine to its limits. In amazing feats of ingenuity and pure “code as an art form”, the scene lives on today, with groups producing breathtaking productions like this and this - bear in mind, both of those are running on a 7Mhz home computer equipped with a floppy disk, 1Mb of memory and a sound chip from 1985. But much as I admire the sheer skill and dedication that takes, it’s the early “single screen” scrolly-text-and-starfield cracktros I’ve always found captivating. They took on a sort of mystical quality for me, hinting at a scene and a culture I could only ever experience from the outside - which is exactly why I spent all those hours in Sinclair BASIC, trying in vain to re-create them, and dreaming of the day I’d eventually have an Amiga of my own. The Jump Back I eventually did trade up to a range of Amiga systems, joined a few “scene” groups myself and threw myself into a variety of activities until exams and the end of my teenage years beckoned. I dabbled with Z80 code back then, and at one point knew enough 68k assembly to bluff my way through - partly from the Amiga’s heyday, partly from a few “embedded systems” modules at University where I had to program a set of traffic lights or lift-controllers. Given there’s not much call for that sort of thing at my $DAYJOB, though, it had all pretty much faded from my memory. I have kept working on a bunch of projects in my spare time, and one of my favourites is my TNFS site - sort of an old-school BBS system or interactive “website” for the Spectrum, which grew out of a fun experiment to see how far I could push Sinclair BASIC. It relies on a modern network card fitted to the Spectrum, which is how I came to be chatting to “Desertkun”, another TNFS-protocol enthusiast. He’s now producing a great new WiFi network card for the Speccy, and was kind enough to send me a few of the prototypes to test out for him. I was massively inspired by his hardware and low-level coding chops, and during one of our video calls where we’d been comparing our development setups, he asked why I didn’t write any Z80 assembly myself. A throw-away comment, but the challenge was set! Now, I couldn’t face re-writing the whole site in asm, but I figured I could produce a self-contained intro to promote it in the style of the early “BBStros”, and finally be one of the cool kids with a scene production of my own :) I mean, how hard could it be ? (ooooh - foreshadowing!) Dev Environment My development environment through this was pretty straightforward, and is the same stack I use for developing my TNFS site. I just used a Makefile-driven build system which ran my code through the Pasmo assembler, my fork of zmakebas to build BASIC files, and the FUSE emulator for testing. For final testing on the real hardware, I uploaded my .tap files to my local TNFS server where I could run them on my +3. A few additional tools I have to call out because they ended up making a big difference - one is the amazing web-based “asm-editor” I discovered while looking up Z80 instructions. Not only does this site have a great reference of all the Z80 instructions, but it also has an editor where you can run example code and see how the memory and/or various registers change state. Take for example, the djnz instruction - you can build it and step through the example loop construct one instruction at a time. Or try my example of an add instruction in the screenshot to see how the carry flag works when a bit gets shifted out of a register. Although it uses a slightly different syntax to Pasmo (so I couldn’t drop my code directly in it), it massively helped when manually stepping through things. And lastly, probably the most significant debugging tools I used on this project - a notepad and pen, and my two dogs (say “Hi!” to Biscuit & Pebble…) I’ll write some more about this in the wrap-up, but this really was a highly unusual project for me, coming from decades of much higher-level languages and constructs. Most of my z80 code I only ever really understood after drawing out the bytes and bitmasks, keeping a table of register flags and drawing chunks of screen memory out by hand. And I found my evening walks with the two dogs provided ideal rubber duck exercises, although I’m not sure what they both made of my protracted mutterings about the hl register pair. Either way, debugging-by-dog is highly recommended! The Starting Point So, let’s get started. I followed a great “Hello, world!” example from futurice.com to validate my build environment. Beyond that, the first thing I wanted to do was load in my logo and background image I’d use as a “stage” for the remainder of the planned intro. I wasn’t really sure what I was going to do at this point, just that I wanted my logo at the top, and a scrolltext along the bottom row of the screen. As my TNFS site header already looked kinda demoscene-y, I made a quick edit putting in place two blue guide-bars inside which I’d put further content. Memory map courtesy of breakintoprogram.co.uk A Spectrum SCREEN$ file (usually displayed as loading screens) is just a dump of screen memory, starting from byte 16384, and running for 6912 bytes. The weird layout of this is very relevant later, but in order to display it all you need to do is load your file into that memory location. After a few hour’s work of reviewing Speccy internals and following various guides, I had a very simple starting point for my demo that served as the basis for everything else that came after. org $8000 screen EQU $4000 ; address of the first byte of screen memory, 16384 in dec scrlen EQU 6912 ; total length of the screen memory inc. attributes ula EQU $FE ; I/O port for the ULA to control the border black EQU 0 ; Spectrum colour number, the exact same ones BASIC uses start: ld a,black ; Set the border colour to black using the ULA out (ula),a ; Copy my logo header picture to screen memory ld hl,header ; HL = location of my screen file in this code ld de,screen ; DE = start of screen memory ld bc,scrlen ; BC = 6912 bytes to copy ldir ; block copy, see https://jnz.dk/z80/ldir.html ; busy loop - rest of intro goes here :P hold: halt ; sleep until the next interrupt (1/50 second) jr hold ; then jump back and sleep again, for ever header: incbin "assets/header.scr" ; my logo header/background end start Not much to look at now, but this simple starting point introduced me to important concepts like interfacing with the Spectrum’s hardware (ULA chip to start with, and AY sound chip later) via the out instruction, how to pull in binary files using Pasmo’s INCBIN directive, using the Z80’s block copy ldir instruction, the use of register pairs for 16-bit addressing, and simple branching to labels. Hello World The next step was to print something on the screen and explore some of the Speccy’s built-in ROM routines, which are somewhat analagous to syscalls on modern operating systems. There are plenty of disassemblies and guides to the Spectrum ROM available on the internet, one of the best commented and linked one is at https://skoolkid.github.io/rom/. Using this as a reference alongside the various “Hello, world!” tutorials showed me how this sort of thing is built up: at EQU 22 ; "at" control character used to position the cursor row EQU 11 ; coordinates where to print the message col EQU 9 prstring EQU $203C ; where the pr_string routine lives in ROM ld de,msg ; DE = address of the first character ld bc,msglen ; BC = how many characters to print call prstring ; print the lot ; busy loop is the same... msg: db at,row,col ; equivalent of "PRINT AT 11,9" in BASIC db "Hello, world!" msglen EQU $-msg ; 16 bytes in all, pasmo shortcut, $=program counter I ended up mostly not using the ROM routines in my code as they dragged in all sorts of things I didn’t need, but it was massively useful to understand how they worked as they introduced me to yet more commonly-used constructs. For example, the PR_STRING routine defined here shows how you can build a loop over each character. If you’re just starting out, I highly recommend going over the 8 lines in that routine with a notepad and pen, working out the contents of the registers and following the loop constructs. I also made a version of it in asm-editor you can try. If you click that link, you’ll see a version of the code loaded into the web editor. Click “Build”, and then step through the code using the “Step” button - although no text will be actually displayed (I skipped over the call to the Spectrum ROM “restart” vector that does this), you’ll see the various states of the registers and for example the BC register counting down as each byte of the string is processed. Adding Some Style Problem is, the Speccy’s built-in font is not exactly dripping with demoscene credibility. I wanted to use some stylish fonts and this turned out to be super easy - a quick search turned up Jim Blimey’s awesome font collection, which included a ready-to-use set of assembler files and some instructions which soon led me to these additions in my code: ; CHARS is the address the ROM's printing routine reads to find the font. ; Picking our own font is simply a matter of over-writing this chars EQU $5C36 ; from Jim's docs - POKE 23607=5C36 in hex ld hl,myfont-256 ; HL = font address - 256 as per docs ld (chars),hl ; from now on the ROM draws with it! ; rest of code is the same myfont: include "textfont.asm" ; "Cartoon" font from jimblimey.com There we go! Now that’s looking a little more elite. Sorry, I mean 31337. Strap in folks, we’re leaving lamer city… So at this point, a month or so in to my dabblings and I’d started to get a reasonable understanding of common idioms and was starting to feel like this was a project that might actually go somewhere. The problem started when I moved on to trying to implement actual demo effects: It became very apparent, very quickly, just how much I didn’t know about how this all worked. Not to mention the fact that at this level, you’re really closely exposed to the physical hardware intricacies, including the design decisions and trade-offs that the hardware designers had to make when working with the extremely limited specs of the early 1980s. Cursed Screen Layout The first such problem - and the cause of probably 90% of my pain - is the Speccy’s extremely weird screen layout. Rather than standard bitmapped display you might expect on more modern hardware, it is instead split into 3 sections, each with a set of interleaved rows (so if you keep adding 1 to a screen address, eventually instead of reaching the next row, you’ll instead end up 8 rows down, and so on until you hit the bottom of the section and then loop back to the row underneath where you started!) followed by a block of “attribute” bytes which determine the colours of each 8x8 block. The attribute blocks are the reason why each 8x8 character cell can only have two colours (a PAPER and INK attribute) which led to the garish “colour-clash” of spectrum games and distinctive style where artists try to keep inside 8x8 blocks as much as possible. But it was the layout of the bitmap portion that is such a mind twister. Download the video You can see this illustrated whenever a game reads in a loading screen from tape. You can see each section built up with the interleaved rows one at a time, and then finally the colour and other attributes (like flashing ). There’s a lot of detail at the fantastic Break Into Program site. In the defense of the designers, they were working with extremely limited hardware and I don’t think the Speccy was ever imagined as a games machine. When you start shuffling bytes around, you realise that this approach is really optimised for displaying text which is neatly arranged into 8x8 character boundaries. For example, using this “scrambled” bit order, if you have a screen address in the hl register pair, you can quickly get to the next pixel line of a given address by simply incrementing the “high” byte. There’s a bunch of other “cheap moves” you can make by simply shifting bits around: Move Instruction Right 8 pixels inc l Left 8 pixels dec l Down 1 pixel line inc h Up 1 pixel line dec h Down 1 character row add 32 to l It was a reasonable choice for a machine that would probably spend a lot of it’s time displaying BASIC program listings - it’s only when you start trying to write demo or sprite routines that it starts to feel really weird. This also means you’ll pretty quickly need a routine to convert X,Y addresses to the relevant memory addresses. Again, L Break Into Program has a useful routine and if you disassemble more or less any spectrum game or demo, you’ll find a version of this procedure somewhere. And yes, this all became horribly relevant later on… The Scroller Download the video Admittedly, not the most interesting demonstration - but this was the first time I had made something move on the Spectrum’s screen with assembly! I watched this with pride more times than I care to admit :) I had a snazzy logo and “Hello World” text, but that doesn’t make for a very interesting intro! The first effect I wanted was the scrolltext - without that, it’s not really an intro. Now, the Amiga had all kinds of hardware sprites, blitter operations, custom chips but the Spectrum had none of that. I was going to have to work out how to do things the hard way - “banging on the metal”, literally by shifting bits around the screen memory by hand and having the CPU do all the work. This is where understanding the Speccy’s weird screen and character cell layout is so important. It turns out there’s a neat trick as long as I stay inside one character row - there’s a RL instruction, which takes a byte and “rotates” it left. It inserts whatever is in the carry flag into the rightmost bit, and whatever gets shifted out ends up in the carry bit again. That means if you string a bunch of them together, you can move a set of pixels across the screen - the moment they “fall off” one character cell, they end up in the carry flag and then the next rl instruction inserts them at the beginning of the next character cell to the left. Repeat 32 times, and you’ve just moved a pixel (or set of pixels) across a line of the screen: linestart EQU $4880 ; leftmost byte of the line 12 rows down lineend EQU linestart+31 ; rightmost byte column ($489F) linelen EQU 32 ; one whole line is 32 bytes (character cells) across dot EQU %00000001 ; the dot "shape", just one pixel lit at the far right end newdot: ld a,dot ; load the dot shape (only rightmost pixel lit) into a ld (lineend),a ; store it in the rightmost byte of the line, pixel is now lit frame: halt ; wait for the next frame, otherwise it whizzes across too fast to see ld hl,lineend ; hl = last (rightmost) byte of the line ld b,linelen ; loop counter, 32 bytes to work through or a ; trick to clear the carry flag, or against itself leaves a register ; unchanged but clears various bits including the carry flag ; see https://jnz.dk/z80/or_r.html shift: rl (hl) ; rotate this byte left (00000001 -> 00000010) dec hl ; point hl at the next byte to the left djnz shift ; loop construct: b=b-1 and then jump back to shift label until b=0 jr c,newdot ; now we've shifted the whole line, so if the carry flag is set now it means ; the dot has just left the screen, so we jump back to the start jr frame ; otherwise it is still somewhere on the screen, so keep shifting! Download the video Hell yeah. It’s almost a proper scrolltext now! Wrapping this in another loop that increments h each time (remember - that gets us moving down a scanline) gets us moving an entire character cell. Here you can see it moving an entire row of my “Hello world” message. There was however a lot more work needed to make a proper scrolltext, with each letter appearing smoothly. I started off by just printing an entire character at a time on the right-hand edge of the screen - it worked, but was pretty ugly as you saw each new character appear at once in the right-hand side of the screen, scrolling 8 pixels over and then the next character flashed up. Instead, I wanted to make each character appear pixel by pixel and that required a bit more bit juggling. The routine I ended up with effectively streams each character in, line by line, pixel by pixel using the font data directly instead of calling the ROM print character routine. It does this by looking up the ASCII code for a character, and then fetching the corresponding font representation into a 8-byte buffer, one byte for each line of data. The font data starts with the space character (character code 32), so a lookup is simply font code base address + (ascii code - 32) * 8 to get to the bits for that letter. Arranged into an 8x8 grid, the bits for the letter H in the font data look like this. For each row of bits, I shift the line left using a neat trick. The byte is loaded into the a register, and then by adding itself to itself - add a,a we shift the value left (in binary, multiplying by 2 moves everything over one bit) so that the pixel I want to draw ends up dropping into the carry flag. This is an idiomatic way of doing it in Z80 code as it’s faster and smaller than the sla instruction. And every cycle quickly adds up when you’re re-drawing 256 bytes every frame! The character buffer then looks like this, with the top line shifted. Now, with the hl register pair pointing at the correct location on the screen, I can then use the rl trick discussed above. This shifts a scanline from the bottom character row of the screen left by one pixel and draws my pixel in the rightmost position by moving it in from the carry flag. Looping 32 times over this moves the entire row by 1 pixel with my new pixel inserted at the right. I then repeat this step again using inc h to move down one scan line until the entire character column has been drawn. At this point, the character buffer looks like this, and all 8 lines of the bottom screen row have all been shifted left by one bit by looping over all 32 character columns. The whole thing then repeats another 7 times until the entire character has been smoothly scrolled onto the screen. So just to re-state this because I think it’s worth the emphasis - just to scroll a message across the bottom of the screen, we’re having to loop over and re-draw 256 pixels every frame! It shows how much faster assembly is than the BASIC interpreter built into the spectrum’s ROM. I found it amazing to see my code finally working and imagining all the bits flying around and registers flapping away. It really makes me appreciate just how much effort went into creating the games I played back then. Music The original Amiga module I converted. A proper 1980s ear-worm! Of course, any good intro needs some music. On the Amiga, the standard was the “tracker” module format, which has a long and involved history of different forks, versions and tweaks. A song is built up from a series of patterns, each made up of rows of instructions. Each instruction usually includes note or pitch information, which sample to play and various parameters such as volume, effects - or in the case of some instructions, which position in the song to jump to. In many ways, it’s almost like a programming language for music. Using ProTracker as an example, a typical note cell is 4 bytes, shown on-screen as something like C-2 01 C20. That breaks down into three fields: the note and octave (C-2), the sample number (01), and the effect and its parameter (C20 - in this case, “set the volume to $20”, which is half of the maximum $40). A close-up of Protracker playing a tune. Note the VUmeters - another classic demo effect I would pinch later on! For an impressive demonstration of what’s possible with a tracker and to see what the note data looks like on-screen, check out the work of h0ffman, and in particular his winning “Professional Tracker” entry from the Revision 2014 competition. He’s an undisputed master of the science (or art!) of tracking, and his “Secrets of Protracker” talk gives a great overview of what’s possible. The Amiga’s sound hardware far eclipsed anything else on the market at the time, and the ZX Spectrum is paltry by comparison. The original 48K models only offered a rudimentary “beeper”, but the later 128K models included a 3-channel AY-3-8912 sound chip. This was very popular in 8-bit micros of the time, and a more-or-less identical variant was also used in the Atari ST. While it only offers basic waveforms and sound processing, it does enable multi-channel “chip music”, and so it became the mainstay of the ZX Spectrum demoscene. It also spawned a variety of SoundTracker clones on the Spectrum itself, although most musicians these days prefer to work in modern tools like Vortex Tracker II, which runs natively under Windows. The Conversion Pex looking back on his demos - this starts at the point where he features my letter and plays a bit of my cover version! For my intro, I wanted to port an Amiga module - and I had the perfect one in mind. One of my favourite Amiga music disks was “Sounds Of Gnome”, released in 1989 by the Swedish duo “Mahoney & Kaktus”. Mahoney also wrote NoiseTracker, one of the first really widely used trackers on the Amiga, and the program that served as my teenage introduction to making computer music of my own. Back in 2018 I made a rock cover of one of the other tunes on that disk, and wrote to Mahoney (real name “Pex”) about it. He ended up showing my “music video” at a demo conference, which I am eternally grateful for! So it seemed only fitting that I mangle another song from that collection with a Spectrum conversion… Sorry, guys! I picked the track “Milkman” which was written by “Glue Master”, an associate of Mahoney’s who had a few of his tracks featured on the compilation. It’s an ideal track for converting: It’s short (only 7 patterns in total), most of those patterns share the same chord sequence, and it looked fairly easy to squeeze the original 4 channels down into the Spectrum’s 3. Plus, it’s an incredibly catchy tune and I knew it well - I’ve been listening to it for 35+ years and often jam along to it on guitar or bass. The conversion started off pretty easily: all I really had to do was copy the patterns note-for-note from the Amiga mod, which I had open in OpenMPT as my Windows tracker. Below is a session with both trackers open on the same pattern - the original Amiga mod on the left, and my 3-channel Spectrum conversion on the right. Note the 11.7 in the 3rd channel of the Spectrum version. This is a “pitch slide down” effect in Vortex Tracker syntax, which drops the pitch by about a quarter-tone. It’s repeated on the next line, so the overall effect is a slide down from the A# that leads in to the next bass note. The original Amiga mod does the same thing using its own syntax - those are the 202s you can see on the same notes, at the bottom of the 4th track. Using just a single “beep” sound for everything was enough to check everything was working, and after a few weeks of hacking on it and re-arranging things in the evenings, I had a basic version which sounded surprisingly good for a first draft: Download the MP3 instead. I have to give a special mention to this forum post which was a massive help getting me started. It’s probably the best introduction to Vortex Tracker I’ve found - many, many thanks to the original author for taking the time to write it all up! The real challenge was making it sound as close to the original as possible. That meant building up a library of better-sounding samples for the different parts, and making extensive use of Vortex Tracker’s “ornaments”. Vortex Tracker comes with a great selection of sounds, and fortunately I’m also a weirdo who likes to listen to chiptunes in the background while I work! So whenever I found something particularly enticing, I filed it away for later pilfering inspiration. A Vortex Tracker sample isn’t really a “sample” in the Amiga sense of a recorded sound - it’s a definition of how a note sounds, one line per frame. Each line can mix in a tone or the white noise generator (useful for snare effects and suchlike), along with various other parameters. Ornaments, on the other hand, give you extra control over what pitch a note plays - and this enables really useful tricks like “arpeggio chords”. For example, an ornament of 0,4 makes the channel switch rapidly (25 times a second) between the note being played and the one 4 semitones above it. It happens so quickly that it sounds much like two notes played at the same time, which means you can build up full-sounding triad chords using only two channels. Take the opening chord in my fully converted version, Cm: It plays C in the first channel and the minor 3rd (D#) in the second, then I apply an ornament to the second channel to bring it up 4 semitones to the 5th (G). That gives all three notes of the chord, while keeping the 3rd channel free for other parts. As well as making much more efficient use of the limited 3 channels, this also gives Spectrum music that characteristic “warbling” sound, which I find really appealing in a retro kind of way! Between tricks like this and samples that mix tones with white noise (to make a combined “bass-snare” sound, for example), I managed to condense the full track down to 3 channels. Many months later, I have to say I’m really pleased with the final result. Playback The original site that was home to Vortex Tracker, documentation and other resources appears to be offline at the moment. I managed to grab a copy of everything I needed from archive.org - you’ll want the PTxTools.7z file for the playback routines discussed here. The playback was simple in theory: As this overview notes, you basically just pull in the player routine, include your module file and call the playback routine once per frame in your main loop. The catch is, none of the source code versions supplied in the archive worked with my Pasmo assembler. Fortunately, there is a pre-compiled binary object shipped alongside the source (VTII10bG in the PTxTools/PT3Play directory). This just has to be loaded in at address $C000 - this cannot be changed, as it has lots of absolute addresses baked in. My code to handle module playback now looks something like this, with the binary module loaded in place: ; Define the start address of the player routine and functions we need player EQU $C000 ; hard-coded org address of binary player plinit EQU player+3 ; init function in docs, module address in hl plplay EQU player+5 ; play and move on one frame ; from the docs - this "analyzes PT3 module header and prepares ; corresponding note and volume tables" ld hl,moduleimg call plinit ; main loop hold: halt call plplay call scroll ; other effects / routines go here... jr hold moduleimg: incbin "assets/music.pt3" Starfield Download the video Well, that didn’t work as hoped. TNFStro - tortoise edition. This brings me to the main event. No self-respecting cracktro is complete without a starfield! My first, naive approach to the classic starfield effect was to scatter random stars across the screen, then move down each scan-line applying the same rl trick I’d used for the scroll-text. I figured I could get parallax by shifting each row a different amount: One pixel for the first row, two for the second, three for the third, then back to one again, all the way down the screen to give the impression of several “fields” of stars moving at different speeds. It turned out there were two major problems with that approach. Firstly, shifting an entire row smeared whatever else was on it along with the stars - which I’d expected, and had filed away as a problem for future me. The bigger issue was speed: by the time I’d finished the first three rows I’d already performed hundreds of shift operations, and it was nowhere near fast enough to fit inside a single frame. Everything crawled across the screen, and the music playback slowed down so much that you could actually hear the arpeggio ornaments warbling away as separate notes. Clearly I was going to have to keep track of the individual stars instead. I found this routine, which was more-or-less what I had in mind and started me off with the idea of a structure to hold the state of each star. It also uses a screen address lookup much like the one from “Break Into Program”. Download the video Dammit. Back with another funeral dirge rendition :( That got things moving, but the co-ordinate lookup and tracking proved expensive to do (it has to run for every star, every frame as well as keep track of the old position for erasing) and I’d been ignoring the bigger question how to display stuff on top of the starfield. My original idea was simply to draw the stars and then paint text over them each frame, which blew the frame budget just as comprehensively as my first attempt. If I wanted something more interesting than an empty starfield, I’d have to keep track of which cells were occupied by text and avoid drawing stars in them in the first place, rather than over-painting them every time. After lots of scribbling in my notepad and visualising rows of bits, I eventually solved both challenges by “cheating” fairly liberally. So now, I don’t generate a random starfield at all. Instead, I built a table of pre-calculated Y and X position pairs: stdata: defb 109, 25, 88,182, 42, 96, 155,226 defb 59,254, 137,169, 160, 84, 125,193 ; ... and so on, for 32 stars ... This saves faffing about with an RNG, and once I have a layout that looks good I know it’ll always look good. I can also “fudge” things and ensure no two stars share the same y co-ordinate which sidesteps a whole class of problems like stars sharing a scanline, and having to deal with them overtaking each other. The “random” layout is generated by a simple Ruby script: #!/usr/bin/env ruby PAIRS = 32 PER_LINE = 4 # pairs per line Y_RANGE = 40..175 # exclude rows taken up by my logo & bars X_RANGE = 0..255 raise "y range too small" if Y_RANGE.size < PAIRS # no duplicate y values ys = Y_RANGE.to_a.sample(PAIRS) pairs = ys.map { |y| [y, rand(X_RANGE)] } pairs.each_slice(PER_LINE) do |row| body = row.map { |y, x| format('%3d,%3d,', y, x) }.join(' ') puts "defb #{body.chomp(',')}" end When the routine initialises, I convert those co-ordinate pairs into a table that tracks the state of each star. So rather than storing a position and translating it to a screen address every frame, each of my star records now looks like this (offsets from the base address): STSCR EQU 0 ; screen address of the byte the star is in, e.g. $4123 STOCC EQU 2 ; a pointer to the "occupancy check" table cell STMASK EQU 4 ; the star's bit pattern, e.g. %00010000 STSTEP EQU 5 ; "speed" - num. of pixels this star travels per frame The key thing is that there are no X/Y co-ordinates at all. For each star I store the screen byte it sits in and the bit mask within that byte, so it’s already in the form the screen writes need. That means no address conversion per frame, just simple bit shifting and rotation. Moving a star is then dead simple. I rotate its mask left with rlca, and when the bit rotates out of bit 7, it lands back in bit 0 with the carry flag set. That’s the signal I need to move the star one character cell to the left, which is one of the “cheap moves” from earlier. Because I’m tracking which cell each star is in, the collision check comes almost for free. That’s what the second pointer is for: STOCC (Star Occupancy) moves in step with STSCR through a table holding one byte per character cell. The “typewriter” routine sets a byte to 1 for every cell containing a text character or the cursor, so checking whether a star is hidden behind text is a single or instruction. If the cell is occupied, I skip drawing the star but carry on rotating and stepping it along until it reaches a cell where it can be displayed: ld l,(ix+STOCC) ld h,(ix+STOCC+1) ld a,(hl) ; A = the occupancy check for this cell or a ; test A against zero jr nz,stmove ; it's occupied, so leave the screen alone Parallax is still handled by moving each star a different number of pixels per frame, but the cost is a lot lower this time as I’m only touching the cells the stars actually occupy, rather than every byte of every row. Download the video That’s looking more like it! The typewriter routine is a simple copy of the font data from memory, and is very cheap as we can use the “cheap moves” to quickly fetch the 8x8 block. I also skip drawing any space character so it leaves the “occupancy cell” unmarked. This means the stars keep drifting through the gaps in the text - you can see here the odd star passing in between the words. I switched to ALL CAPS writing for the final version which helps the effect even more as the font is quite blocky, so you don’t really notice stars skipping the spaces inside a glyph at all. Misc Notes A few odds and ends that didn’t warrant a section of their own… VU Meters Some sort of graphic display bouncing along with the audio playback was another common early demo trope. I did originally consider a real-time graphic equaliser, but that would have been far too complex, probably in terms of spare cycles per frame, and definitely in terms of my limited mental capacity at this point! So I settled for a simple set of bouncing meter bars instead. It’s worth a mention mostly because it gives me an excuse to link to the awesome chibiakumas website! I just love the late 90s web design on display - one can argue that readability and accessibility take a hit, but it’s just so much fun to encounter a site that still looks like this. It’s a clear labour of love and there’s a wealth of content there as well, if your eyeballs are up to it. Their guide on Making Sound with the AY-3-8910 was what showed me how to get the data I needed to draw the meter bars. The examples write a register number to $FFFD to select a register, and I realised that once a register is selected, I could use the in instruction to read its value back out instead of writing a new one. As the page says, R8, R9 and R10 hold the channel amplitudes, so they feed nicely into the height parameter for drawing a bar. Getting the amplitude for channel A is then as simple as: ld a,8 ; Channel A register call ayread ; ... rest of code here ... ayread: ld bc,$FFFD ; Register select port out (c),a in a,(c) ret Twinkle, Twinkle, Little Star This is a simple effect that makes the header logo a little more interesting. I’m not sure where I originally got the idea - I’ve definitely seen something like it on a few late 80s/early 90s demos, though. All I wanted was to pick random star dots in the logo background and animate them. Here’s the header image loaded in ZXPaintbrush with the character cell grid showing. By happy chance, there are four stars which each sit neatly inside a single character cell with enough surrounding space, so they can be used to give an animated “twinkle” effect by drawing a cross out from the centre point and back in again. These dots map to the following co-ordinates, which target the top scanline of each fully-grown star (two pixels up from the centre): twkdata: defb 1,5 ; char row 0, col 5, centre y=3 ink 5 defb 1,20 ; char row 0, col 20, centre y=3 ink 1 bright defb 26,7 ; char row 3, col 7, centre y=4 ink 4 defb 25,22 ; char row 3, col 22, centre y=3 ink 6 bright The “twinkle” routine itself is simple enough: it adds a pixel on either axis to grow the star, waits a few frames, then shrinks it back down again. The interesting bit was how I made the twinkle order pseudo-random. Remember that my starfield was entirely pre-calculated from a data table generated by a Ruby script, which meant I’d never actually needed a random number generator in assembly. From Jonathan Cauldwell’s “How To Write Spectrum Games” e-book, I found another great “hack” which simply walks through the start of the Spectrum’s ROM, picking out random-looking bytes as it goes. As he says, he uses it in most of his games, and it does the job in a really simple way - as long as you stay below the block of structured, repeating data that sits 8Kb into the ROM. twkrand: push hl ld hl,(twkseed) ld a,h and 31 ; keep it within the first 8k of ROM ld h,a ld a,(hl) ; the "random" byte inc hl ld (twkseed),hl pop hl ret Out Of Space About halfway through writing the intro, I hit a fairly predictable problem: I had run out of memory. In an attempt to keep everything self-contained in one block of code, I was pulling all of the assets (the screen background, the player binary, the music file etc.) into the program itself, and then using the ldir block copy instruction to move each one into its correct location. Since that meant effectively storing every block twice, and the player routine had a hard-coded start address of $C000, I quickly ran out of room and my code started crashing into the playback routine. The simplest option was to split things out into separate code blocks, load each one directly to the address it needed to live at, and wrap the lot in a multi-stage BASIC tape loader: 10 CLEAR 32767 20 BORDER 0: PAPER 0: INK 0: CLS 30 LOAD "" CODE 40 LOAD "" CODE 50 LOAD "" CODE 60 RANDOMIZE USR 32768 This loads the main program, then the player routine directly into $C000, and finally the background screen straight into screen memory. It does mean the background starts appearing before the demo has fully loaded, but as I imagine most people will be seeing this running in an emulator or on my TNFS site, it doesn’t really matter. Plus, at this point I was in danger of disappearing down yet more rabbit holes (I still really want to work out how to do multi-colour border effects!) and I’d never have got this thing released. The Zen Of Z80 This whole project is a really weird one to look back at. On the one hand, I’ve fulfilled a childhood ambition and have something I’m very proud of. It’s also pretty unusual these days to end up with a binary where you can say pretty much what every single byte is doing and the story of how it got there. But on the other hand - I now have an answer for why I don’t code in assembly: It’s because I value (what’s left) of my sanity! The thing is, in order to write code like this you have to start thinking like the machine itself. You have to visualise the registers and the status flags flapping away, graphics as lines of bits slotted into strange orders, loops and conditionals as binary logic and so on. Getting this close to the hardware definitely brought about a greater sense of attachment to the hardware of my childhood, and it’s easy to see why assembly coders and sceners get so passionate about it. That said, I’m in no hurry to start re-writing my body of work in assembly! The projects I really enjoy are those that give me an excuse to learn something for the sheer hell of it, and to slow down a little from the ever-increasing velocity and demands of the modern work world. Going back to Z80 code is probably about the furthest I could have taken this, short of going into hardware hacking. I found it at times an intriguing puzzle, often a frustrating exercise that nearly had me throwing in the towel at several stages. This project has certainly taken the longest to go from the “idea” stage of any given feature to any kind of meaningful output. True, I didn’t spend every day of the last year working on it - my actual coding time was probably only a few hours over a couple of evenings a week. But I’ve certainly been thinking about it and pondering it most days (as my dogs will attest). The biggest breakthroughs and “aha!” moments usually didn’t come from behind the keyboard; they came from scribbles in my notebook and thinking about processor states while doing something unrelated. It has however given me massive appreciation and respect for the coders who pull this stuff off and make it look easy. And that goes double for those kids and bedroom coding superstars who managed all of this back in the 80s, and had to work it all out by experiment themselves. I only managed to get this far because of numerous books, online tutorials, GitHub repositories with sample code, YouTube videos… I can’t imagine how much longer this would have all taken me if the only resources I had were my Spectrum, a cassette tape recorder and a notepad. So, as I draw a line under this project - for now! - I raise a glass, and in the words of h0ffman: “Shout out to the hackers, graphicians and protrackers.”

13 hours ago • 1 votes
CalVer 26.0: 10th Anniversary Edition

A decade ago, a little bit of history was made. I didn't realize it, but a colleague made a great point, one of those real mind-changing points that seem too obvious to admit same-day. But, the next day, calver.org was born. At the time my team maintained the Python infrastructure for eBay and PayPal, and we were stuck deciding whether we were really ready for a "major" 1.0 release. Semantic Versioning was the only game in town and "major" means "big", right?! Thankfully, a wiser colleague mentioned: Ubuntu and Twisted don't struggle with version number debates. They slap a date on it and keep shipping. In fact, their date-based versions were even better because you always knew where it stood, in terms of updatedness and support. The only problem is that no one really knew about it. Somehow, this problem solving versioning alternative, arguably as old as history itself, had gone nameless for millenia, conspiring to make me feel foolish in an office meeting. Never again! Ten years of adoption Fast forward 10 years, we've seen CalVer adopted by Apple, Nvidia, JetBrains, and countless others. (We have a timeline!) The site may have more inbound links than any other project of mine. Apple made the biggest jump, at WWDC 2025: iOS went from 18 to 26 macOS from 15 to 26 watchOS from 11 to 26 and visionOS from 2 to 26 All landing on one, consistent number like a car's model year. I still remember the texts from the Venn diagram fanbase of my friends who love Apple and reasonable versioning. No such texts from when NVIDIA announced calendar versions across the GPU Operator, RAPIDS, and its monthly NGC containers, but still very cool. Open source, too: Home Assistant, pip, CockroachDB, and yt-dlp all ship on dates, with plenty more on the users page. The conversation even reached the language core; PEP 2026 proposed versioning CPython as 3.YY, and it almost happened, too. And it's never too late, time marches on! Fixing the notation But I don't think I got every detail right from day 1. That's the main motivator for CalVer 26. It's high time to start righting a couple idiosyncratic token design choices, starting with some additions: Meaning Before 26.0 26.0 Full year YYYY YYYY Short year (6, 16) YY YY Zero-padded year (06, 16) 0Y 0Y Short month (1 ... 12) MM M Zero-padded month (01 ... 12) 0M 0M Short week (1 ... 52) WW W Zero-padded week (01 ... 52) 0W 0W Short day (1 ... 31) DD D Zero-padded day (01 ... 31) 0D 0D Seeing double First, the doubled letters. From the first version (16.6), MM and DD meant the unpadded month and day, which reads backwards to anyone who knows date formats (ISO 8601's YYYY-MM-DD, Java, moment.js, day.js), as some community members correctly pointed out. I was ready to flip them, until I checked what people actually use: most projects with a YY.MM.MICRO badge (conda, Twisted, Ansible's tooling) don't pad, and more than a dozen other version management tools (like bumpver and bump-my-version) implement the old meaning. So, it's too late to flip MM's meaning. Instead, 26.0 deprecates it and offers a more explicit and hopefully clearer option: M is the short month, 0M the padded one, and MM is a technically-retired synonym for M. In case you're wondering, the explicit 0M was me being overinspired by Ubuntu's approach, perhaps: 6.06 pads its month but not its year, and YY.0M says exactly that. To pad or not to pad I think it's worth a detour into why padding is even a thing anyways. It's become important now that new ecosystems have emerged that enforced SemVer formatting semantics, and I wanted clear guidance about on the spec site. SemVer forbids leading zeros outright, so Cargo rejects 26.04.0 and Go modules reject v26.04.0. Even Python's packaging spec normalizes leading zeros away, so you can tag 2026.08.19 if you want, but PyPI will still show 2026.8.19. NVIDIA's GPU Operator docs put it this way: "Zero padding is omitted for month to be still compatible with semantic versioning." CalVer was always intended to drop in where SemVer was used. So 26.0 recommends unpadded (YYYY.M.D) as a sane "pure" default for software libraries. But libraries are not the only objects of versioning schemes. The exception is a version that becomes a filename, an image tag, or an object-store key that gets listed lexically. There, padding keeps 26.10 sorted after 26.09, which is why Ubuntu, NixOS, and NVIDIA's own NGC containers pad. More evidence of teams designing their versions. We love to see it. Our FAQ has a longer discussion of the padding issue, as well. Optional segments There was never any rule against them, but 26.0 makes optional trailing segments more explicit with square brackets. Now, yt-dlp's scheme can finally be written down: YYYY.0M.0D[.MICRO]. For the CalVer badges I could find on GitHub, they all stay valid for now. I've got a note on the deprecated spellings and a new copy-paste badge section for new ones. What else is new? It's always a great time to add more citations to the site. A spec changelog; the spec now versions itself: 16.6, 19.7, 26.0. A FAQ: breaking changes, same-day releases, and padding. The users page, rebuilt by category, with past users of note (schemes change; that's fine) and tooling. Case studies: Apple and NVIDIA in, yt-dlp replacing youtube-dl. Much of the thinking behind these changes happened in the GitHub issue tracker over the years, and 19 or so issues close with this release. That's where ideas for CalVer should go, so by all means, open an issue, and we'll get it sorted! In due time, of course. In closing, I can't believe I still love belaboring these numbers so much. Thanks to all (but especially Mark, Glyph, Hugo, issue reporters, translators, and maintainers) for the discussion, and ultimately making the most timely versioning system a timeless classic. See also 2016 announcement Designing a version My Yap on Why CalVer beats Semver

yesterday • 1 votes
"You didn't do it right"

Four sincere attempts at OKRs, four failures, and every time: "you didn't do it right." Maybe the framework doesn't fit you -- so how do you find one that does?

yesterday • 1 votes
We solved SQLite's single-writer limitation

Multiple concurrent writers. Multiple processes. Same SQLite. No modifications.

3 days ago • 1 votes
If your team is happy, are you doing a good job?

Brilliant jerks, ZIRP-era managers, and how psychological safety lost the plot. Part 3 of my conversation with Dr. Cat Hicks.

4 days ago • 1 votes
📚 BoredReading

You seem to be enjoying this.

Join free to unlock everything.

Create free account

Already have an account? Sign in