Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/02/21 in all areas

  1. Are you thinking of this environment? - https://sites.google.com/view/x16asmenv/home The roadmap suggest that it will be in the ROM for the shipping version.
    1 point
  2. #2 Coding on a system that doesn't have a web browser to distract you from programming. #3 Tinkering with hardware without an other system compile / transfer / test / edit / other system compile ... loop
    1 point
  3. Hello again everyone. I've been wanting to make a game for the X16 lately, but for what I want to do I needed to figure out a good way to stream data off a file from any random position. You can't do that yet within the r38 emulator (as far as I know). You would have to split up the file into smaller ones. However, you can do this with the POSITION command in CMDR-DOS. This does mean you must have an SD card for this to work. The syntax for the POSITION command is: You have to specify both the channel the file is on and the 32-bit position you want to use. Those 5 arguments must be actual byte values, and not ascii representations of the values! In BASIC, it is as simple as: Assembly is more verbose, but it is basically the same idea. You first open the file, set the file offset, read bytes into memory, then close the file. Because there is a lot more code to go through I have included an attachment with the source code of the example. I personally use the ACME assembler, but it shouldn't be difficult to adapt to other assemblers. You should be able to get a program file when you assemble main.asm. Once you have the .prg file built, place it and the TEST file in an SD card image and run it in the emulator. The TEST file includes a bunch of ascii text. I'm interested in retrieving the "HELLO X16!" string without going through any of the padding. The first thing we need to do is open the file. (All of the following code will be in the attachment, so you don't need to copy & paste) ; fs_open ; Opens a file to be read. ; Arguments: ; r0 = Pointer to a null-terminated string that is the filepath to open. ; r1L = Channel to open. ; Assumptions: ; * SD Card is being used and is set to device #8 ; * String in r0 is less than 256 characters. ; * Channel is not 0, 1, or 15. fs_open: !zone { +set_ram_bank RAM_BANK_KERNAL_DOS ; Make sure the ram bank is set to 0. lda (r0) ; Load the first character in the string bne .setup ; Checking for the null-terminator rts ; End early if the input is an empty string. .setup: ldx r1L ; Open passed in channel jsr CHKIN lda #8 ; SD Card in device #8 jsr LISTEN lda r1L ora #$F0 ; $FX = Open file in channel X (r1L) jsr SECOND .loop_init: ldy #0 ; Start at the first character. .send_char: lda (r0),Y ; Read the current character beq .cleanup_and_exit ; Exit if the byte is the null terminator jsr IECOUT ; Send character to the serial bus iny ; Move to the next character bra .send_char ; Keep looping .cleanup_and_exit: jmp UNLSN ; Stop listening and send the filename. } This function was adapted from my execute_dos_command function that I shared in my original post, since opening up channel 15 is how you execute dos commands in the first place. Do note that the high-ram bank must be set to zero for this code to work. Speaking of which, we are going to use a modified execute_dos_command function to run the POSITION dos command, but first we have to setup that command in RAM: ; The channel 15 command that sets the position of a file. DOS_FILE_POSITION: !scr "P" DOS_FILE_POSITION_CHANNEL: !byte 0 DOS_FILE_POSITION_OFFSET: !byte 0, 0, 0, 0 DOS_FILE_POSITION is used as the string pointer for the command. DOS_FILE_POSITION_CHANNEL points to the channel id, and DOS_FILE_POSITION_OFFSET points to the 32-bit offset. In the attachment I created a bunch of macros to help me simplify the code. I'm not going to go through them since it would take too long, so here is an equivalent to the line 20 of the basic code: lda #2 ; Using channel 2 sta DOS_FILE_POSITION_CHANNEL ; Set the channel of the file to 2 lda #$80 ; "HELLO X16!" is located at offset $80 of the TEST file sta DOS_FILE_POSITION_OFFSET ; Store $80 to the low byte ; I technically don't need these 3, since they are never modified. ; stz DOS_FILE_POSITION_OFFSET + 1 ; Store 0 to the middle-low byte ; stz DOS_FILE_POSITION_OFFSET + 2 ; Store 0 to the middle-high byte ; stz DOS_FILE_POSITION_OFFSET + 3 ; Store 0 to the high byte lda #<DOS_FILE_POSITION ; Load the DOS_FILE_POSITION pointer into r0 sta r0L lda #>DOS_FILE_POSITION sta r0H lda #6 sta r1L ; Length of the POSITION command (6 bytes) jsr execute_dos_command_n ; Execute the command to set the file offset to $80 Now that we have the position ready, we now need to read the bytes from the file. To do this we need to set the ROM bank to 2, since that bank contains the function to read bytes. That function is called file_read_block with the arguments: .A is the number of bytes to read and .Y/.X is the destination address to write to. To help with this I wrote some macros to save the ROM bank & call the file_read_block function: ; Read bytes from a file into RAM. !macro m_fs_read_to_address .dest, .length { ldx #<.dest ldy #>.dest lda #.length jsr file_read_block ; ROM bank must be set to 2 before this is called! } ; Saves the current ROM bank and sets it to the CBDOS bank. !macro m_fs_start_reading { +push_current_rom_bank_onto_stack +set_rom_bank ROM_BANK_CBDOS ; ROM_BANK_CBDOS = 2 } ; Restores the previous ROM bank. !macro m_fs_stop_reading { +pull_current_rom_bank_from_stack } You can find the macros: set_rom_bank, push_current_rom_bank_onto_stack, and pull_current_rom_bank_from_stack in the banks.inc file in the attachments source code. After the bytes are read, the file finally needs to be closed so that the channel can be used for other files. To do that you simple call the fs_close function. ; fs_close ; Closes a channel so that it can be used again. ; Arguments: ; r0L = Channel to close. ; Assumptions: ; * SD Card is being used and is set to device #8 ; * String in r0 is less than 256 characters. ; * Channel is not 0, 1, or 15. fs_close: !zone { ldx r0L ; Open passed in channel jsr CHKIN lda #8 ; SD Card in device #8 jsr LISTEN lda r0L ora #$E0 ; $EX = Close file in channel X (r0L) jsr SECOND jmp CLRCHN ; Close the channel and return } When you look at the main.asm file, you'll see these macros being used: FILENAME: !SCR "TEST", 0 CHANNEL_FILE = 2 ; Channel to use. Can be any value within [2, 14] SRC_OFFSET = $80 ; Position within the file DEST_ADDRESS = $20 ; RAM address to write to READ_LENGTH = 10 ; Number of bytes to copy main: +m_fs_open CHANNEL_FILE, FILENAME ; Open the file +m_fs_set_file_position CHANNEL_FILE, SRC_OFFSET ; Set the current position of the file. +m_fs_start_reading ; Saves the current ROM bank, and sets it to the CBDOS code bank. +m_fs_read_to_address DEST_ADDRESS, READ_LENGTH ; Read data from the file into RAM. +m_fs_stop_reading ; Restores the original ROM bank. +m_fs_close CHANNEL_FILE ; The channel must be closed before using it again. exit: rts ; Return to basic. I'm hoping that those macros make it easy to understand what is happening conceptually. You can look at fs.asm for more information on what they are actually doing. The indenting isn't required, I just think it looks nice (like python). When you run the code in the emulator you'll see that nothing happens on the basic screen. When you dump the RAM, you should see that the "HELLO X16!" message appeared at offset $20. If you have any question or comments, then please leave a reply and I'll try to get back to you as soon I can. filepos-example-v1.1.zip
    1 point
  4. I've done some code cleaning the last couple of days. Very rewarding when the code becomes more compact, more readable, and more stringent. So far I've reduced the binary by almost 200 bytes. Some time ago, I watched a few lectures on Clean Code by "Uncle Bob". Very inspiring, even though not all paradigms may be used in assembly, if you want things to fly fast. A nice weekend to all of you!
    1 point
  5. I think everyone can use whatever they know for this kind of task. Albeit admittedly some tools allow for more comfort than a Hex editor. I am using Python for generating binary data. It would look like this struct_1 = [12, 13, 14] struct_2 = [0, 80, 0, 90, 0, 100] data = struct_1 + struct_2 + struct_1 # appending data is as easy as this. data_bytes = bytes(data) f = open("DATA.BIN","wb") # "wb" stands for write binary f.write(data_bytes) f.close()
    1 point
  6. I have started a new tutorial series on YouTube to teach you how to program in Assembly Language for the X16 and other 6502-based systems. The first lesson -- and introductory overview of the basics -- is now on YouTube:
    1 point
×
×
  • Create New...

Important Information

Please review our Terms of Use