Writing stuff in Assembly for Sega Genesis #1

The first article dedicated to writing games for the classic Sega Genesis console in Motorola 68000 Assembler.

Let’s write the simplest endless loop for Sega. For this we need: an assembler, an emulator with a disassembler, a favorite text editor, a basic understanding of the structure of the Sega rom.

For development, I use my own Gen68KryBaby assembler/disassembler:

https://gitlab.com/demensdeum/gen68krybaby/

The tool is developed in Python 3, for assembly, a file with the extension .asm or .gen68KryBabyDisasm is supplied to the input, the output is a file with the extension .gen68KryBabyAsm.bin, which can be run in the emulator or on a real console (carefully, step away, the console may explode!)

Roms disassembling is also supported, for this you need to put a rom file to the input, without the .asm or .gen68KryBabyDisasm extensions. Opcode support will increase or decrease depending on my interest in the topic, the participation of contributors.

Structure

The Sega rom header occupies the first 512 bytes. It contains information about the game, name, supported peripherals, check sum, and other system flags. I suppose that without a title, the prefix will not even look at the rom, thinking that it is incorrect, like “what are you giving me here?”

After the header comes the Reset subroutine, from which the m68K processor starts its work. Well, it’s just a small matter – to find the opcodes, namely, the execution of nothing (!) And the transition to the subroutine at the address in memory. Googling, you can find the NOP opcode that does nothing and the JSR opcode that performs an unconditional jump to the argument address, that is, it just moves the carriage to where we ask for it, without any whims.

Putting It All Together

One of the games in the Beta version was the donor of the title for the rom, at the moment it is recorded in the form of hex data.

 ROM HEADER:

 00 ff 2b 52 00 00 02 00 00 00 49 90 00 00 49 90 00 00 49 90 00 ... etc. 

The program code so-but is a declaration of the Reset / EntryPoint subroutine in 512 (0x200) bytes, NOP, carriage return to 0x00000200, so we get an infinite loop.

Assembly code of Subroutine Reset / EntryPoint:

 SUBROUTINE_EntryPoint:
    NOP
    NOP
    NOP
    NOP
    NOP
    JSR 0x00000200

Complete example along with rom title:

https://gitlab.com/demensdeum/segagenesissamples/-/blob/main/1InfiniteLoop/1infiniteloop.asm

Next, assembly:

 python3 gen68krybaby.py 1infiniteloop.asm 

Run rom 1infiniteloop.asm.gen68KryBabyAsm.bin in debugger mode of Exodus / Gens emulator, see that m68K correctly reads NOP, and endlessly jumps to EntryPoint at 0x200 on JSR

Sonic should be showing V here, but he left for Wacken .

Links

https://gitlab.com/demensdeum/gen68krybaby/

https://gitlab.com/demensdeum/segagenesissamples

https://www.exodusemulator.com/downloads/release-archive

Sources

ROM Hacking Demo – Genesis and SNES games in 480i < / p>

http://68k.hax.com/

https://www.chibiakumas.com/68000/genesis.php

https://plutiedev.com/rom-header

https: //blog.bigevilcorporation.co.uk/2012/02/28/sega-megadrive-1-getting-started/

https : //opensource.apple.com/source/cctools/cctools-836/as/m68k-opcode.h.auto.html

Flame Steel Engine Runner

I present to your attention Flame Steel Engine Runner – a platform for running multimedia applications based on the Flame Steel Engine toolkit. Supported platforms are Windows, MacOS, Linux, Android, iOS, HTML 5. The focus of application code development has shifted towards scripting – at the moment JavaScript support has been added using TinyJS, the toolkit itself and the engine will continue to be developed in languages ​​close to hardware (C, C ++, Rust, etc.)
Flame Steel Engine Runner Demo
On the page below, you can spin the cube, write JavaScript code, upload models, sounds, music, code using the Upload files button, and start from the main.js file using the Run button.
https://demensdeum.com/demos/FlameSteelEngineRunner/

KleyMoment – glue for script files tool

I present to you a utility for pasting script files – KleyMoment, also a reverse utility for pasting files back. The utility can be used to merge JavaScript files into one.
The tool is implemented in Python 3, has the simplest command line interface of the form:

python3 KleyMoment.py extension Files directory Containing Files output File

For example, recursively gluing js files from the scripts directory to the output.js file

python3 KleyMoment.py js scripts output.js

Also a utility for pasting files back AntiKleyMoment, accepts a glued file as input, for example:

python3 AntiKleyMoment.py output.js

Repository:
https://gitlab.com/demensdeum/kleymoment /

Space Jaguar Action RPG 0.0.4

First Space Jaguar Action RPG prototype for Webassembly:

https://demensdeum.com/demos/SpaceJaguarActionRPG004/

https://demensdeum.com/demos/SpaceJaguarActionRPG004_NOTIMEOUT/

Prepare for long loading (53mb) without any indication.

Space Jaguar Action RPG – space pirate simulator. Features available right now:

  • fly around
  • die
  • eat
  • sleep
  • recruit people
  • look at unstoppable flow of time

Can’t walk in 3D scenes right now, due to bad optimization for web version. It will available in next versions.

Game engine source code, scripts are available under MIT license. All comments and feedback are welcome:

https://gitlab.com/demensdeum/space-jaguar-action-rpg

Linux version screenshots:

How I didn’t hit the guy on the pole or the story of amazing ingenuity

In this post I will write about the importance of architectural decisions in development, application support, in a team development environment.

Self-Operating Napkin – Rube Goldberg

During my youth, I worked on an app for ordering a taxi. In the program, you could choose a pickup point, a drop point, calculate the cost of the trip, the type of tariff, and, in fact, order a taxi. I got the application at the last stage of the pre-launch, after adding several fixes, the application was released in the AppStore. Already at that stage, the whole team understood that it was implemented very poorly, design patterns were not used, all components of the system were tightly connected, in general, it could be written into one large continuous class (God object), nothing would have changed, so how classes mixed their boundaries of responsibility and, in their mass, overlapped each other in a dead cohesion. Later, the management decided to write the application from scratch, using the correct architecture, which was done and the final product was implemented by several dozen B2B clients.

However, I will describe a curious incident from past architecture, from which I sometimes wake up in a cold sweat in the middle of the night, or suddenly remember in the middle of the day and start laughing hysterically. The thing is that I could not hit the guy on the pole the first time, and this brought down most of the application, but first things first.

It was an ordinary working day, one of the customers received a task to slightly modify the application design – it is banal to move a few pixels up the icon in the center of the screen on the pickup address selection screen. Well, having professionally evaluated the task in 10 minutes, I raised the icon 20 pixels up, suspecting nothing at all, I decided to check the taxi order.

What? Does the app no ​​longer show the order button? How did it happen?

I could not believe my eyes, after raising the icon by 20 pixels, the application stopped showing the continue ordering button. Rolling back the change, I saw the button again. Something was wrong here. After spending 20 minutes in the debugger, I got a little tired of unwinding spaghetti from calls to overlapping classes, but I found that * moving the picture really changes the logic of the application *

It was all about the icon in the center – the man on the pole, when he moved the map, he jumped to animate the camera movement, this animation was followed by the disappearance of the button below. Apparently the program thought that the man shifted by 20 pixels was in a jump, so, according to internal logic, it hid the confirmation button.

How can this happen? Does * the state * of the screen depend not on the pattern of the state machine, but on the * representation * of the guy’s position on the pole?

Everything turned out to be so, every time the map was drawn, the application * visually pick * in the middle of the screen and checked what was there, if there was a man on a pole, then this means that the animation of the map shift was over and the button had to be shown. In the case when the man is not there, it means that the map is shifting, and the button must be hidden.

In the example above, everything is fine, firstly, this is an example of the Goldberg Machine (abstruse machines), secondly, an example of the developer’s unwillingness to somehow interact with other developers in the team (try to figure it out without me), thirdly, you can list all the problems by SOLID, patterns (code smell), MVC violation, and more.

Try not to do this, develop in all possible directions, help your colleagues in their work. Happy new year everyone)

Links

https://en.wikipedia.org/wiki/Rube_Goldberg_machine

https://en.wikipedia.org/wiki/SOLID

https://refactoring.guru/refactoring/smells

https://en.wikipedia.org/wiki/Model-view-controller

https://refactoring.guru/design-patterns/state

Guess Band

In this post I will describe how to work with the fasttext text classifier.

Fasttext is a machine learning library for text classification. Let’s try to teach her to identify a metal band by the name of the song. For this, we use supervised learning using a dataset.

Let’s create a dataset of songs with group names:

__label__metallica the house jack built
__label__metallica fuel
__label__metallica escape
__label__black_sabbath gypsy
__label__black_sabbath snowblind
__label__black_sabbath am i going insane
__label__anthrax anthrax
__label__anthrax i'm alive
__label__anthrax antisocial
[etc.] 

Training sample format:

{__label__class} {example from class} 

Let’s train fasttext and save the model:

model = fasttext.train_supervised ("train.txt")
model.save_model ("model.bin")

Let’s load the trained model and ask to identify the group by the song name:

model = fasttext.load_model ("model.bin")
predictResult = model.predict ("Bleed")
print (predictResult) 

As a result, we will get a list of classes that this example looks like, indicating the level of similarity by a number, in our case, the similarity of the Bleed song name to one of the dataset groups.
In order for the fasttext model to be able to work with a dataset that goes beyond the boundaries of the training sample, the autotune mode is used using a validation file (test file). During autotune, fasttext selects the optimal model hyperparameters, validating the result on a sample from the test file. The autotune time is limited by the user independently by passing the autotuneDuration argument.
An example of creating a model using a test file:

model = fasttext.train_supervised ("train.txt", autotuneValidationFile = "test.txt", autotuneDuration = 10000) 

Sources

https://fasttext.cc
https://gosha20777.github.io / tutorial / 2018/04/12 / fasttext-for-windows

Source code

https://gitlab.com/demensdeum/ MachineLearning / – / tree / master / 6bandClassifier

x86_64 Assembler + C = One Love

In this article I will describe the process of calling C functions from assembler.
Let’s try to call printf ( “Hello World \ n!”); and exit (0);

section .rodata
    message: db "Hello, world!", 10, 0

section .text
    extern printf
    extern exit
    global main

main:
    xor	rax, rax
    mov	rdi, message    
    call printf
    xor rdi, rdi
    call exit

Everything is much simpler than it seems, in the section .rodata we describe the static data, in this case the string “Hello, world!”, 10 it is a newline character, and will not forget it annihilate the.

The section of code declare outside of the printf function, exit libraries, stdio, stdlib, also declare main entry function:

section .text
    extern printf
    extern exit
    global main

In the case of the return function rax pass 0, can be used mov rax, 0; but to accelerate the use xor rax, rax; Further, in the first argument is a pointer to a string:

rdi, message

Next call external C functions printf:

main:
    xor	rax, rax
    mov	rdi, message    
    call printf
    xor rdi, rdi
    call exit

By analogy, transfer case 0 in the first argument and calling exit:

    xor rdi, rdi
    call exit

As the Elves say:
Who does not listen
He eats plov @Alexander Pelevin

References

https://www.devdungeon.com/content/how-mix-c-and-assembly
https://nekosecurity.com/x86-64-assembly/part-3-nasm-anatomy-syscall-passing-argument
https://www.cs.uaf.edu/2017/fall/cs301/reference/x86_64.html

Source Code

https://gitlab.com/demensdeum/assembly-playground