-
Retrospective of RetroChallenge 2024
11/01/2024 at 07:05 • 0 commentsRetrospective of RetroChallenge 2024
The period for RetroChallenge 2024 concluded on October 31. This project, which explores the combination of retro computing and modern AI, considers this pairing to be both unique and challenging. Although this project didn’t reach its initial goal, I’d like to summarize my progress here.
The project achieved the following milestones:
Completed Items:
- Verification of MIDI hardware functionality
- Creation of a MIDI file parser in Python
- Development of a MIDI player program (Z80 assembly) on actual CP/M and SCM machines to play MIDI files (requires pre-conversion of songs using the Python program)
- Development of a MIDI parser (Z80 assembly) for CP/M
Incomplete Items:
- Creation of a MIDI player (Z80 assembly) on CP/M, program to directly read MIDI files was not completed.
Insights and Know-how Gained:
- Techniques for creating Z80 programs using ChatGPT
- Review methodologies for Z80 programs with ChatGPT
- Effective debugging methods using the ASM80.com online assembler and simulator
- A library of CP/M and Z80 subroutines developed with ChatGPT
Through this challenge, I found that creating ready-to-use programs with ChatGPT is challenging. It was most efficient to create small subroutines and combine them into a program, which I believe is the most valuable takeaway from this challenge.
In summary, I believe the project reached about 80% completion. I am particularly eager to continue developing the MIDI player that runs on an actual CP/M machine.
(Still) To be continued…
-
Development with Online Assembler, IDE, and Simulator
10/24/2024 at 06:46 • 0 commentsDevelopment with Online Assembler, IDE, and Simulator
I continue to develop programs for the Z80 using ChatGPT. It has become clear that the programs created by ChatGPT contain many errors, and human intervention is necessary to correct them. To confirm these errors, it is most reliable to execute the created program and check the results. Combining small programs makes it easier to detect errors. However, when it comes to the stage of combining programs and verifying their operation, downloading to the actual RC2014 machine takes time.
I discovered that efficiency can be increased by combining online assemblers and simulators. I tried Martin Maly's [ASM80.com](https://www.asm80.com/) (online assembler, IDE, simulator).
---------- more ----------The process flow for program development using ChatGPT and ASM80.com is as follows:
- Create a program by conversing with ChatGPT.
- Copy and paste the completed program into ASM80.com and assemble it. A HEX file is created on the online IDE.
- Switch to the CP/M simulator of ASM80.com and load the HEX file created in step 2 into memory. (Since ORG $100 is specified in the assembler, it is loaded into memory from address $100.)
- Immediately create a COM file with the SAVE command of CP/M (CCP).
- Example: A>SAVE 1 B:TEST.COM
- Execute and check the results.
- Example: A>B:TEST.COM
- By using ZSID.COM, the Z80 debugger, on the A drive, you can also trace the program.
- Example: A>ZSID B:TEST.COM
Although not implemented this time, it is also possible to link with a GitHub repository, so you can publish the created program as it is.
(TO BE CONTINUED)
-
Creating Small Programs with ChatGPT
10/20/2024 at 06:48 • 0 commentsCreating Small Programs with ChatGPT
Due to security-related updates, the hackaday.io web editor was out of service for a while, which delayed my blog updates. However, the project has been steadily progressing.
Anyway, I’ve been using ChatGPT to create Z80 assembler programs. Initially, I thought it would be easy to generate Z80 assembly code. For small programs like a MIDI player, I could create something functional with just minor tweaks. However, when I tested it with slightly more complex programs, I realized things weren’t so straightforward.
---------- more ----------For example, there were several issues that made the generated code unusable as is:
1. Lack of knowledge about BDOS calls:
- Registers passed as arguments to BDOS calls were incorrect.
- The wrong arguments were passed to BDOS calls. For instance, in the case of the OPEN BDOS call, the correct argument is HL = FCB (File Control Block) address, but a pointer to the filename string was passed instead.
- It didn’t account for registers that are destroyed by BDOS.2. Incorrect register saving and restoring:
- The order of PUSH and POP instructions was wrong. It would PUSH AF and BC in order but POP them in the same sequence, leading to errors.3. Use of instruction combinations that are not valid for Z80.
While ChatGPT often generates reasonably correct code in Python, it seems to struggle more when it comes to Z80 assembler. There is potential to improve this by designing GPTs specifically for Z80 assembly, but this will take time. Therefore, I’ve decided to try splitting up the tasks. I plan to create small programs, have ChatGPT generate Z80 code, point out its mistakes, and gradually refine the code until it works.
I intend to store the programs I create in a GitHub repository, as I believe they will be useful for future program development.
https://github.com/kuwatay/MIDI-FOR-RC2014/tree/main/ai_playground
-
creating a github repo
10/14/2024 at 06:42 • 0 commentsProject Update: MIDI Interface for RC2014
I have created a GitHub repository to store the latest version of the programs developed for this project, along with their descriptions. You can check it out for the most up-to-date files and documentation.
https://github.com/kuwatay/MIDI-FOR-RC2014
singlePlayer is a dedicated program for playing a single song. It pre-processes a MIDI file by parsing it with a MIDI parser, converting it into a data table, and then creating an executable program. It comes with a Makefile that can generate both CP/M COM files and binaries for SCM.
Stay tuned for more updates as the project progresses!
-
Towards the Next Milestone
10/10/2024 at 00:16 • 0 comments1. Towards the Next Milestone
The next goal is to create a program to play MIDI files using Z80 assembler. By specifying it on the command line, it is planned to make it possible to play MIDI files directly with the RC2014 computer alone.
Since a file system is required, the platform will be migrated from SCM to CP/M. Also, accurate timing generation for music playback requires timer interrupts. It would be good to have a Z80CTC card or a Z180 with a built-in CTC. Alternatively, J.B. Langston's designed TMS9918A Video Card for RC2014 can generate interrupts with vertical sync signals (1/50sec), which might be better.
To handle MIDI files, it is necessary to write a MIDI parser in Z80 assembler, which seems to be more complex than previous programs. Therefore, first, we will consider the MIDI file parser and the program for real-time management of playback time.
---------- more ----------2. Structure of MIDI Files
Since the parsing of MIDI files is written in Python, it will be completed by replacing it with Z80 assembler. It seems easy to create if you ask ChatGPT. Also, so far, only NOTE messages have been handled, but it is necessary to modify it to handle other types of messages as well.
The existing Python MIDI file parser supports only single-track files and has limitations. Some MIDI files contain multiple tracks to handle multiple instruments simultaneously. Reading multiple tracks is just a matter of executing a single track multiple times, so it doesn't seem too difficult.
However, MIDI files with multiple tracks contain time information for each track, so to play them synchronously, it is necessary to devise a way to read them in real-time. Specifically, it is necessary to manage the playback time for each track and calculate the time to trigger the next event. This part seems to be a fairly complex algorithm. Also, since it is music playback, processing delays are fatal. It is necessary to adopt the fastest possible algorithm.
3. Looking at MIDI Files
Anyway, it seems necessary to check the structure of the MIDI files available. Therefore, I asked ChatGPT to create a program to dump MIDI files in Python.
Use it as follows:
$ python midi_parser.py Greensleeves.mid
- Format type: 0
- Number of tracks: 1
- Time division: 384
- Parsing track 1...
- Track length: 2256 bytes
- Delta time: 0, Total time: 0 ticks
- Meta event: Type 0x58, Length: 4, Data: b'\x04\x02\x18\x08'
- Delta time: 0, Total time: 0 ticks
- Meta event: Type 0x51, Length: 3, Data: b'\x1a(m'
- Delta time: 0, Total time: 0 ticks
- Meta event: Type 0x3, Length: 21, Data: b'Elec. Piano (Classic)'
- Delta time: 0, Total time: 0 ticks
- Program Change - Channel: 0, Program Number: 0
- Delta time: 0, Total time: 0 ticks
- Note ON - Channel: 0, Note: 38, Velocity: 50
- Delta time: 96, Total time: 96 ticks
- Note OFF - Channel: 0, Note: 38, Velocity: 0
- Delta time: 0, Total time: 96 ticks
- Note ON - Channel: 0, Note: 45, Velocity: 50
- Delta time: 96, Total time: 192 ticks
- Note OFF - Channel: 0, Note: 45, Velocity: 0
- Delta time: 0, Total time: 192 ticks
- Note ON - Channel: 0, Note: 50, Velocity: 50
- Delta time: 96, Total time: 288 ticks
- Note OFF - Channel: 0, Note: 50, Velocity: 0
- Delta time: 0, Total time: 288 ticks
- Note ON - Channel: 0, Note: 53, Velocity: 50
- Delta time: 96, Total time: 384 ticks
- Note OFF - Channel: 0, Note: 53, Velocity: 0
- Delta time: 0, Total time: 384 ticks
- Note ON - Channel: 0, Note: 50, Velocity: 50
- Delta time: 96, Total time: 480 ticks
- Note OFF - Channel: 0, Note: 50, Velocity: 0
- Delta time: 0, Total time: 480 ticks
- Note ON - Channel: 0, Note: 45, Velocity: 50
- Delta time: 96, Total time: 576 ticks
- Note OFF - Channel: 0, Note: 45, Velocity: 0
- Delta time: 0, Total time: 576 ticks
Each MIDI message is assigned a delta time. This indicates the timing to generate the MIDI message. It is called an EVENT, and it indicates the elapsed time from the previous message to generate the EVENT. It is necessary to accumulate the delta time from the beginning of the track and determine the timing to generate the EVENT (i.e., send the MIDI message). Each track is independently assigned a delta time. The MIDI player needs to keep track of playing point in every tracks.
(To Be Continued)
-
Playing "Greensleeves"
10/08/2024 at 11:09 • 0 commentsPlaying "Greensleeves"
In my previous programming endeavors, I was able to send note messages, but I couldn't play an actual song.
As the next step, I decided to parse a MIDI file, extract its data, create an assembly table, and give it a try.
As usual, I asked ChatGPT to help me create a Python program (!) that parses the MIDI file and converts it into an assembler DB format.
The following program was created.
---------- more ----------For the test, I used the following MIDI file as the basis:
https://onlinesequencer.net/1256965
I got a table with a set of MIDI data. After that, I modified and combined it with the MIDI sending program I had previously created in assembly, and the program was completed.
After assembling it, I successfully got it running on the SCM. Here the result;
By following this procedure, I am now able to generate an assembly program that plays music from a MIDI file.
Since I’m not using interrupts, I need to manually adjust the delay times to change the tempo.
All in all, I’m glad that I can now play a song.
My next goal is to modify the program to parse MIDI files on CP/M using Z80 assembly. -
Creating GPTs of Z80 Specialist
10/07/2024 at 07:40 • 0 commentsCreating GPTs of Z80 Specialist
1. Motivation
Large Language Models (LLMs), such as ChatGPT, generate programs based on information available on the internet, utilizing language models. For example, if you request it to create a "Hello World" program for CP/M, it will generate a reasonably functional program.
ORG 100h ; CP/M programs start at 100h LD DE, message ; Load the address of the message into DE LD C, 9 ; BDOS function 9 (print string) CALL 5 ; Call BDOS RET ; Return to CP/M message: DB 'Hello, World!$' ; Message to print, ending with a '$'
However, since LLMs do not possess specialized knowledge, if you ask them to create a "Hello World" using the SCM API, the generated program may look somewhat suspicious.---------- more ----------ORG 100h ; Start of the program LD HL, message ; Load address of the message into HL print_loop: LD A, (HL) ; Load the current character into A CP 0 ; Check if it's the null terminator (0x00) JP Z, end ; If zero, end the program CALL 0005h ; Call SCM routine to print a character INC HL ; Move to the next character in the string JP print_loop ; Repeat the loop end: RET ; Return to monitor message: DB 'Hello, World!', 0 ; Message string terminated by 0x00
This happens because the model is relying on general knowledge to generate its answers. By using specialized knowledge, we could likely obtain more refined results.2. Programming Assistant for Small Computer Monitor (Z80)
To emphasize specialized knowledge and obtain better answers, I decided to create a custom GPT. GPTs can change the policy for generating responses. In this case, I instructed it to refer to the SCM reference manual and user manual when creating programs.
The prompt I provided was as follows:This GPT is designed to be a programming assistant for working with Z80, an 8-bit microprocessor commonly used in vintage computing and embedded systems. It helps users write, debug, and optimize assembly code for small computer monitors or other Z80-based systems. It will refer SCM user guide and reference manual in knowledge area. It offer practical tips, explanations, and sample code, adapting to the user's knowledge level. The assistant stays focused on Z80 programming tasks, providing guidance on registers, memory management, instruction sets, and general programming flow in Z80 assembly. It ensures clarity in all interactions while avoiding unnecessary jargon.
As intended, it successfully created a program using the SCM API.
ORG 0x8000 ; Start the program at 0x8000 (example address) LD HL, message ; Load the address of the message into HL print_loop: LD A, (HL) ; Load the current character into register A CP '$' ; Check if the character is the string terminator ('$') JR Z, end_print ; If the character is '$', jump to end the print loop CALL api_print_char ; Call the SCM API function to print the character INC HL ; Move to the next character in the string JR print_loop ; Repeat the loop for the next character end_print: CALL api_newline ; Print a new line using SCM API RET ; Return to SCM message: DB 'Hello, World!$' ; Message string terminated with '$' ; SCM API calls api_print_char: LD C, 2 ; SCM API function $02: output character CALL 0x0030 ; SCM API handler RET api_newline: LD C, 7 ; SCM API function $07: output newline CALL 0x0030 ; SCM API handler RET
RTS $30 is batter for API call.
You can access the prototype GPTs from here.
-
AI That Plays Melodies
10/06/2024 at 08:59 • 0 commentsAI That Plays Melodies
Now that I was able to generate note messages, I asked ChatGPT to create a program that plays a melody.
I followed these steps to make the request:
- As in the previous attempt, I asked ChatGPT to generate a program in Z80 assembler to produce note signals. This time, I specified both the address of the ACIA status register and the data register.
- Since the A register was being overwritten in the MIDI transmission subroutine, I asked ChatGPT to fix this issue.
- I requested a modification to store the pitch information in a table format.
- I then asked ChatGPT to generate the pitch sequence for "Greensleeves" in the table. (It seems that ChatGPT couldn’t generate it correctly.)
- Since the instruction
IN A, (B)
was being generated, I requested a correction.
With these steps, the assembler program was created, which I downloaded to my computer and generated a HEX file. Although it wasn’t "Greensleeves," I was able to play some melody.
https://chatgpt.com/share/67026d7d-ab60-8003-9f54-4ff0b840cc6b
---------- more ----------ORG $8000 ; Program starts at address $8000 START: LD HL, NOTE_TABLE ; Point HL to the start of the note table NEXT_NOTE: LD A, (HL) ; Load the next note number from the table CP 0 ; Check if the note number is 0 (end of the table) JR Z, DONE ; If 0, end the program CALL SEND_NOTE_ON ; Send Note-On message for this note CALL LONG_DELAY ; Long delay before sending Note-Off CALL SEND_NOTE_OFF ; Send Note-Off message for this note INC HL ; Move to the next note in the table JR NEXT_NOTE ; Repeat for the next note DONE: RET ; Return to the caller when done ; Subroutine to send a Note-On message SEND_NOTE_ON: LD A, $90 ; Load Note-On status byte (channel 1, note-on) CALL SEND_MIDI ; Send the status byte LD A, (HL) ; Load the note number from the table CALL SEND_MIDI ; Send the note number LD A, $7F ; Load velocity (127, maximum) CALL SEND_MIDI ; Send the velocity RET ; Return to the main routine ; Subroutine to send a Note-Off message SEND_NOTE_OFF: LD A, $80 ; Load Note-Off status byte (channel 1, note-off) CALL SEND_MIDI ; Send the status byte LD A, (HL) ; Load the note number from the table CALL SEND_MIDI ; Send the note number LD A, $00 ; Load velocity (0, note-off) CALL SEND_MIDI ; Send the velocity RET ; Return to the main routine ; Subroutine to send a MIDI byte, preserving A SEND_MIDI: PUSH AF ; Preserve register A by pushing AF to the stack WAIT_READY: IN A, ($A0) ; Read the status register from address $A0 BIT 1, A ; Check if transmit data register empty (bit 1 = 1) JR Z, WAIT_READY ; Wait until the data register is ready POP AF ; Restore A from the stack OUT ($A1), A ; Send the byte to the data register at address $A1 RET ; Return to the main routine ; Long delay routine (for longer duration between notes) LONG_DELAY: LD BC, $FFFF ; Load a larger value into BC for longer delay DELAY_LOOP: DEC BC ; Decrement BC LD A, B ; Check upper byte OR C ; Combine upper and lower bytes JR NZ, DELAY_LOOP ; Continue looping until BC = 0 RET ; Return after delay ; Data table of MIDI note numbers for "Greensleeves" melody (0 terminates the table) NOTE_TABLE: DB $40, $43, $45, $47, $45, $43, $40 ; A3, C#4, E4, F#4, E4, C#4, A3 DB $40, $43, $45, $47, $45, $43, $40 ; Repeat similar phrase DB $45, $47, $48, $47, $45, $43, $40 ; E4, F#4, G#4, F#4, E4, C#4, A3 DB 0 ; End of the table
-
First Attempt: Generating MIDI Note-On and Note-Off with ChatGPT (Continued)
10/06/2024 at 06:53 • 0 commentsFirst Attempt: Generating MIDI Note-On and Note-Off with ChatGPT (Continued)
1. Code Review
I conducted a detailed review of the program generated by ChatGPT. The following issues were identified:
- Incorrect ACIA initialization Since ACIA is already initialized by SCM, I decided to omit the initialization step and commented out the corresponding section.
- Destruction of the A register in the SEND_BYTE routine The A register, which stores the data to be transmitted, was being overwritten. To fix this, I modified the routine to push the A register onto the stack at the entry point and pop it before outputting the data.
- Incorrect address for the ACIA data register The address should be $A1 instead of $A0.
- Infinite loop After outputting the Note-On and Note-Off messages, the program returned to the start. For testing purposes, I modified the program to output only once and then return to the monitor.
---------- more ----------The manually corrected program is as follows:
; Z80 Assembly Program to send MIDI Note messages via ACIA at $A0 ; Program starts at $8000 ORG $8000 ; Program starting address START: ; Initialize ACIA ; LD A, $03 ; Control register: 8 data bits, no parity, 1 stop bit, divide by 16 clock ; OUT ($A0), A ; Write to ACIA control register ; Send MIDI Note On (Channel 1, Note 60, Velocity 127) CALL MIDI_NOTE_ON ; Delay (for demonstration purposes) CALL DELAY ; Send MIDI Note Off (Channel 1, Note 60, Velocity 0) CALL MIDI_NOTE_OFF ; End of program loop ; JR START ; Jump to the beginning to repeat RET ; Routine to send MIDI Note On MIDI_NOTE_ON: LD A, $90 ; Status byte for Note On, Channel 1 CALL SEND_BYTE LD A, $3C ; Note number (Middle C) CALL SEND_BYTE LD A, $7F ; Velocity (maximum) CALL SEND_BYTE RET ; Return from subroutine ; Routine to send MIDI Note Off MIDI_NOTE_OFF: LD A, $80 ; Status byte for Note Off, Channel 1 CALL SEND_BYTE LD A, $3C ; Note number (Middle C) CALL SEND_BYTE LD A, $00 ; Velocity (0) CALL SEND_BYTE RET ; Return from subroutine ; Routine to send a byte to the ACIA SEND_BYTE: ; Wait until ACIA is ready to transmit PUSH AF WAIT_TX_READY: IN A, ($A0) ; Read status register BIT 1, A ; Check if transmit buffer is empty (bit 1) JR Z, WAIT_TX_READY ; If not empty, wait POP AF ; Send the byte OUT ($A1), A ; Send byte to ACIA data register RET ; Return from subroutine ; Delay routine (simple loop for demonstration) DELAY: LD BC, $FFFF ; Load BC with a large value DELAY_LOOP: DEC BC ; Decrement BC LD A, B ; Check if BC reached 0 OR C JR NZ, DELAY_LOOP ; If not zero, keep looping RET ; Return from subroutine
After making these corrections, I saved the program on my computer as midi_test.asm.
2. Assembly Process
To execute the above program, I created a HEX file using a Z80 assembler. Although I usually develop on a Mac mini, I used
sjasm
andbin2hex
for Z80 development. The following commands can be used to assemble the program:$ sjasm test_ai.asm $ bin2hex -o0x8000 -b16 test_ai.out > test_ai.hex
In practice, I automated the process using a Makefile:
.PHONY: clean .SUFFIXES: .out .hex .asm TARGET : midi_test.hex .out.hex: bin2hex -o0x8000 -b16 $< > $@ .asm.out: sjasm $< clean: rm -f *.out *.hex *.lst
Run the make command generate the following messages.
$ make sjasm midi_test.asm Sjasm Z80 Assembler v0.42c - www.xl2s.tk bin2hex -o0x8000 -b16 midi_test.out > midi_test.hex rm midi_test.out
3. Test Environment
To debug, I needed to verify that the MIDI messages were being sent correctly. Instead of using a MIDI sound module, I used a MIDI interface on my Mac, which made it easier to check the program's behavior. I looped back the messages from the RC-2014 using a Roland UM-ONE-MK2 MIDI interface I had on hand. Below is a diagram of the setup:
4. Results
Dropping the HEX file into the SCM console sends the file. You can verify that it was sent correctly using the D command. To execute the program, type
g 8000
in the SC114 console. As expected, both the Note-On and Note-Off messages were output.
By using MIDI Monitor, I was able to directly confirm the MIDI messages. Additionally, I launched GarageBand and configured a software instrument, which played the corresponding sounds based on the MIDI messages.And so, all is well that ends well.
-
First Attempt: Generating MIDI Note-On and Note-Off with ChatGPT
10/05/2024 at 05:51 • 0 commentsFirst Attempt: Generating MIDI Note-On and Note-Off with ChatGPT
As the first step in this challenge, I tried creating a Z80 assembler program using ChatGPT.
While it is well-known that ChatGPT excels at generating programs in languages like Python, I am unsure if it can create a Z80 assembler program. For this attempt, I used "ChatGPT 4.0" (paid version). This version is relatively unrestricted and allows for the creation of customized GPTs, which I plan to try later.
Anyway, I entered the following prompt:
"Show me a program to send MIDI note messages in Z80 assembler. MIDI messages are sent via ACIA at $A0. The program should start at $8000. Please include an ACIA initialize routine."
---------- more ----------As a result, I received the following output:
; Z80 Assembly Program to send MIDI Note messages via ACIA at $A0 ; Program starts at $8000 ORG $8000 ; Program starting address START: ; Initialize ACIA LD A, $03 ; Control register: 8 data bits, no parity, 1 stop bit, divide by 16 clock OUT ($A0), A ; Write to ACIA control register ; Send MIDI Note On (Channel 1, Note 60, Velocity 127) CALL MIDI_NOTE_ON ; Delay (for demonstration purposes) CALL DELAY ; Send MIDI Note Off (Channel 1, Note 60, Velocity 0) CALL MIDI_NOTE_OFF ; End of program loop JR START ; Jump to the beginning to repeat ; Routine to send MIDI Note On MIDI_NOTE_ON: LD A, $90 ; Status byte for Note On, Channel 1 CALL SEND_BYTE LD A, $3C ; Note number (Middle C) CALL SEND_BYTE LD A, $7F ; Velocity (maximum) CALL SEND_BYTE RET ; Return from subroutine ; Routine to send MIDI Note Off MIDI_NOTE_OFF: LD A, $80 ; Status byte for Note Off, Channel 1 CALL SEND_BYTE LD A, $3C ; Note number (Middle C) CALL SEND_BYTE LD A, $00 ; Velocity (0) CALL SEND_BYTE RET ; Return from subroutine ; Routine to send a byte to the ACIA SEND_BYTE: ; Wait until ACIA is ready to transmit WAIT_TX_READY: IN A, ($A0) ; Read status register BIT 1, A ; Check if transmit buffer is empty (bit 1) JR Z, WAIT_TX_READY ; If not empty, wait ; Send the byte OUT ($A0), A ; Send byte to ACIA data register RET ; Return from subroutine ; Delay routine (simple loop for demonstration) DELAY: LD BC, $FFFF ; Load BC with a large value DELAY_LOOP: DEC BC ; Decrement BC LD A, B ; Check if BC reached 0 OR C JR NZ, DELAY_LOOP ; If not zero, keep looping RET ; Return from subroutine
At first glance, it looks correct. I will review the contents in more detail later, but for now, I asked it to assemble the code and display the result.
"Please assemble this program and show me the Intel hex file, which can run on an actual Z80 CPU."
I received the following output:
It seems that I currently don't have access to the required module to generate the Intel HEX file. However, I can provide the bytecode for the Z80 assembly program, which you can use to assemble it using a Z80 assembler that supports Intel HEX output. Here is the bytecode in hexadecimal format, starting at address $8000: 8000: 3E 03 ; LD A, $03 8002: D3 A0 ; OUT ($A0), A 8004: CD 08 80 ; CALL MIDI_NOTE_ON 8007: CD 1A 80 ; CALL DELAY 800A: CD 0E 80 ; CALL MIDI_NOTE_OFF 800D: 18 F6 ; JR START 800F: 3E 90 ; LD A, $90 8011: CD 22 80 ; CALL SEND_BYTE 8014: 3E 3C ; LD A, $3C 8016: CD 22 80 ; CALL SEND_BYTE 8019: 3E 7F ; LD A, $7F 801B: CD 22 80 ; CALL SEND_BYTE 801E: C9 ; RET 801F: 3E 80 ; LD A, $80 8021: CD 22 80 ; CALL SEND_BYTE 8024: 3E 3C ; LD A, $3C 8026: CD 22 80 ; CALL SEND_BYTE 8029: 3E 00 ; LD A, $00 802B: CD 22 80 ; CALL SEND_BYTE 802E: C9 ; RET 802F: DB A0 ; IN A, ($A0) 8031: CB 4A ; BIT 1, A 8033: 28 FB ; JR Z, WAIT_TX_READY 8035: D3 A0 ; OUT ($A0), A 8037: C9 ; RET 8038: 01 FF FF ; LD BC, $FFFF 803B: 0B ; DEC BC 803C: 78 ; LD A, B 803D: B1 ; OR C 803E: 20 FB ; JR NZ, DELAY_LOOP 8040: C9 ; RET
No HEX file was output, but an assembly listing was provided. Of course, I need to verify whether the generated code is correct, and I plan to do that later.
If a HEX file were generated, it would have been convenient, as it could be copied and pasted directly into the Small Computer Monitor. Unfortunately, that was not the case.
From this experiment, I learned the following:
- ChatGPT can generate Z80 assembler programs.
- It has knowledge of MIDI and produced appropriate code.
- It cannot generate HEX files.
By the way, the conversation is publicly available. You can view it from the following link: https://chatgpt.com/share/6700ce0a-70a8-8003-b571-a45570f236b4
POSTSCRIPTAs the result of inspection, I found at least one error exist in the code. The address of data register in ACIA should be $A1, not $A0. I need to change it by myself, or ask CharGPT to correct it.