Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Stefan

  1. Version 0.3.0 of X16 Edit released. Major rework to make the program romable. I have included a pre-built ROM image. There are, however, some steps, if you want to test the ROM version. The steps are described in more detail on the download page, and on my Github page. Change of line break encoding. If in PETSCII mode line breaks are now marked with a single CR. In ISO mode line breaks are marked with a single LF.
  2. I got the ROM version of my program and interrupts working now, finally. I learned some new things in the process. I write it down, should you have any use for it. I use the CA65 assembler. A minimal config file could contain the following: MEMORY { ROM: start = $c000, size = $3ffa, fill=yes, fillval=$aa; IRQ_VECTORS: start = $fffa, size = $06, fill=yes, fillval=$aa; } SEGMENTS { CODE: load = ROM, type = ro; IRQ: load = IRQ_VECTORS, type = ro; } On a maskable interrupt request, the 65C02 processor jumps to the address in $FFFE/$FFFF. Your ROM needs to hold a reference to a valid interrupt handler. Otherwise it's likely that the computer just locks up. That interrupt handler needs to switch to Kernal ROM bank, and call the Kernal interrupt handler in Bank 0/$FFFE-$FFFF. When done it needs to switch back to the ROM bank that was active before, i.e. the ROM bank you are using. The interrupt handler must be stored in RAM. If in your ROM bank, the program execution would continue at the following address in the Kernal ROM as soon as you switch bank, and probably cause unexpected results. There is already such an interrupt handler in RAM location $038B ("banked_irq") when the computer is booted. To use this enter the following somewhere in your code to be stored in the IRQ segment, i.e. in memory addresses $FFFA-$FFFF. .segment "IRQ" .byt $ff, $ff, $ff, $ff, $8b, $03 .CODE In your code you may then change the interrupt vectors in $0314-$0315 as usual. sei lda #<($0780) sta $0314 lda #>($0780) sta $0315 cli Here my custom interrupt handler is stored in RAM address $0780. Normally you would store the handler in ROM, and copy it to RAM on starting your program. My custom interrupt handler looks like this: bridge_irq: lda ROM_SEL pha lda #7 ;assuming your code is in bank 7 sta ROM_SEL jsr irq_handler pla sta ROM_SEL jmp (irq_default_handler) irq_handler is code in your ROM bank that is run during the interrupt. The bridge code is only what's needed to switch between Kernal bank and your bank. Assemble your rom image with the following command: cl65 -v -t cx16 -C yourconfig.cfg -o yourrom.bin <source files> You may attach your ROM image to the standard ROM file with the cat command (on Linux or MacOS at least). This is also what the X16 Kernal project does in it's makefile. For this to work your ROM image must be exactly 16,384 bytes. cat rom.bin yourrom.bin > customrom.bin When starting the emulator, select the custom rom with the -rom option. I don't think it's possible to run code in another ROM bank from BASIC. Instead you may type in the following short startup program in the built-in monitor. .A1000 LDA#$07 ;assuming your code is in ROM bank 7 .A1002 STA$9F60 .A1005 JSR$C000 ;assuming this is the entry point of your code .A1008 RTS
  3. @Ender Thank you. I understand a bit more of what the monitor does now. Vector in ROM bank 5/FFFE = 038b The routine in 038b is called banked_irq, which basically does the following, I think (it's easy to get sidetracked): Saves active ROM bank number on stack Switches to ROM bank 0 (Kernal) Jumps to Kernal FFFE vector. Before that pushes return address and processor status (?) on stack Switches back to the ROM bank we started with Restores registers Exits with RTI My next try will be based on a FFFE vector pointing to the same 038b routine and a custom irq handler stored in RAM pointed to by 0314-0315. The custom irq handler will switch ROM bank and call my code, and when done switch the ROM bank back. Exit with jump to Kernal irq routine.
  4. Hi, I see that @StephenHorn has written an article on interrupts. I have a question on how to setup interrupts if your code is placed in a ROM bank (not the same as the Kernal). I just can't get it to work. Any pointers on how to do this are welcome. The alternatives I tried: Placing bridge code in RAM that is pointed to by $0314-0315. The bridge code change ROM bank, and executes my code therein. When done it restores X,Y,A and exits with RTI (without changing the ROM bank). Storing pointers to my interrupt handler directly in the $FFFE-FFFF in my ROM bank. Either nothing happens, or the emulator crashes. EDIT: I've looked a lot at the monitor code, but I do not fully understand it. One thing is that its interrupt handler seems to exit with a rts. How is that possible? Looking at the compiler config file for the monitor, it's apparent that it includes some vectors, amongst other things, from the Kernal. These two memory ranges are defined: KSUP_CODE2: start = $FB00, size = $03C0, fill=yes, fillval=$AA; KSUP_VEC2: start = $FEC0, size = $0140, fill=yes, fillval=$AA; => Range $fec0-ffff: May include entry points of Kernal routines, and all interrupt vectors It all comes down to what happens on an interrupt: Is the interrupt vector read from FFFE/FFFF in the active ROM bank (and not always ROM bank 0)? I guess that there's no possibility that the processor on interrupt could change the ROM bank before code execution starts. If so, what parts of the Kernal ROM need to be copied to your own ROM to make this work?
  5. OK. I will look into supporting CR line breaks and maybe even CRLF line breaks as alternatives. The user interface could work about the same way as Nano, i.e. you select format after issuing the save command. As to being romable: There's the JSRFAR Kernal function, but I guess that's not available if your code resides in another ROM bank. The JSRFAR is general and there seems to be some overhead for each call that you could avoid by using a specialized bridge, at least for Kernal calls made a lot of times in a loop. I've looked at the BASIC source, but as I'm not familiar with it, it's very hard to exactly understand what's going on. And the BASIC ROM code is also not available if your code resides in another ROM bank. A bridge function in RAM need not be more complicated than this, I think, using a call to CHRIN as an example: bridge_chrin: stz $9f60 ;ROM bank 0 jsr CHRIN ldx #6 ;Return to editor ROM bank, here assumed to be no 6 stx $9f60 rts
  6. Was there ever a standard text file format for the C64? I don't really remember. But I was not doing a lot of text editing on the C64 in the 80s. My feeling is that everyone invented their own solution on the C64. BASIC uses NULL (0) as end of line marker. At least some of the word processors/text editors of the time used screen codes instead of PETSCII. One such example is SpeedScript, that I've tested in VICE. Speedscript furthermore used screen code 31 as end of line marker, i.e. the left arrow character. The text: "HELLO WORLD!<ENTER>" is stored as hex values 00 25 08 05 0C 0C 0F 20 17 0F 12 0C 04 21 1F, where the first three bytes are not part of the text, and 1F is the line break marker. By not using LF as line break marker, we loose compatibility with all modern OS:es. Do we really gain anything by using $OC?
  7. It's not a problem supporting CR line breaks. But is it a good idea to have different standards? I haven't done much thinking on what's needed to make the editor "romable". The editor would fit in a 16 K ROM bank without any further size optimization The editor uses the following Kernal routines: GETIN to read the keyboard SETNAM, SETLFS, OPEN, CHKIN, CHKOUT, CHRIN, CHROUT, READST, CLRCHN and CLOSE for reading and writing files MEMTOP to get banked RAM size I think you would need a bridge in RAM for each of those Kernal functions. A bridge would need to Switch to the Kernal ROM bank Call the Kernal function Switch back to editor ROM bank And return without affecting the communication registers of the Kernal function Looking at the memory map, it seems that the bridge functions could be placed in 0400-07ff. The bridge functions could be stored in the editor ROM bank and moved to 0400-07ff on each startup. Disclaimer: I haven't tested any of this.
  8. The head of the text is always bank 1, address $a000. The memory model is not a simple stream of bytes. The memory pages are organized as doubly linked lists, and every memory page has some metadata to make this possible.
  9. @pzembrod OK. Let me know if there are issues. One thing: As far as I know there is no real text file format standard for the X16, especially how line breaks are to be coded. I have chosen to use Unix style line breaks, that is LF=character code 10 (decimal). That could be a problem for VolksForth if it assumes another form of line break. I would not like to use CR as line break, as that is not recognized by other OS. And don't ask me about those Windows two byte line breaks... I'm not part of the group that decides what's going into the ROM. If they would like to include the editor, that's fine with me. The editor is released under GPL v 3, and may be distributed by anyone under the terms of that license. Would it otherwise help to make a high memory version of the editor, that could stay in RAM at the same time as VolksForth? The program has become a bit large (at present 15KB). I could shrink it by 2 KB by moving the built-in help screen to a file. I'm in the process of cleaning up the code, and might be able to shrink to code further, but it will not be easy to make it substantially smaller than 13 KB.
  10. Nice work! Forth is an interesting language, but I do not know almost anything about how to use it. I've been programming a text editor for the platform (X16 Edit). It would be nice to use the editor for forth coding. I managed to write the smallest hello world program and saved it as a text file on the SD card image. I could import the source file to your interpreter with the include command, and it worked as expected. Even though the interpreter seems to be running in ISO character mode, the source file I imported was interpreted as PETSCII. I don't know if that's a limitation. Comments are, for instance, marked with backslash, which is not available in PETSCII. Please let me know if there is anything I can do to make the editor play nicely with Forth.
  11. It would be great to use the editor for enhanced BASIC programming. I started to look at a solution a couple of weeks ago: Write BASIC code and save as text file (=source) Run a parser/translator on the source file which outputs a tokenized BASIC program I don't know if the parser/translator should be integrated into the editor or if it should be a separate program. The parser/translator could make it possible to write BASIC code with support for labels and long variable names, and without using line numbers. It's feasible, but a lot of work.
  12. @tibi I'm glad you want to try x16edit. If you use the command "x16emu.exe -sdcard sdcard.img -prg x16edit-0.2.3.prg -run" there is no need to copy the prg file to the sdcard image. When starting the emulator with the -prg option, the emulator loads the prg file directly from the host file system. The -run option runs the program automatically as soon as the emulator is started. The error message simply means that x16edit-0.2.3.prg wasn't found, presumably not being in the path where you started the emulator from. The easiest solution might be to stand in the folder where x16edit-0.2.3.prg is saved in the host file system when you start the emulator. Then the command should work without any changes. If you still have problems it may help to copy x16edit-0.2.3.prg to the same folder where the emulator executable is stored. Another solution would be to use an absolute path to the prg file. As I have no Windows installation, I cannot test exactly how you would specify an absolute path, but you could test "c:/downloads/x16edit-0.2.3.prg" or "c:\downloads\x16edit-0.2.3.prg" (assuming that the prg file is stored in the c:\downloads folder. The command would then be: x16edit.exe -sdcard sdcard.img -prg c:/downloads/x16edit-0.2.3.prg -run (if forward slashes work on the Windows version of the emulator) However, it's also possible to copy the prg file to the sdcard image as you did. If you do this, you need to load and run the program in a different way: Ensure that the sdcard image is not mounted in Windows. Mounting the image on two systems at the same time may corrupt the sdcard image. Start the emulator with the following command: x16emu.exe -sdcard sdcard.img In the emulator, first type: LOAD "X16EDIT-0.2.3.PRG" Then type RUN
  13. I like the idea of more structured BASIC programming too, with labels and long variable names. I also think it would be great if you could do that on the X16 directly. I've been thinking about a parser/translator solution. Work flow: Create and edit a source file as raw text and save it to disk. This is the part I've been working on for some time (X16 Edit). Run the parser/translator, which would output a Commodore BASIC prg file to disk. Load and run the prg file as a normal BASIC program. The source file could look like this: message$="Hello" loop: print message$ goto loop Which would be translated into: 10 aa$="Hello" 20 print aa$ 30 goto 20 I've done some initial tests. I managed to write assembly code that analyzes the elements of a line - what part of a line is a token, a string, a number literal, a delimiter, a label definition or a variable name. It's probably a lot of work making this into a functional parser/translator, but it would be doable. However, it would be great to know if somebody else is working on a similar solution.
  14. You can increase a label. Without testing the code, I think it in this case will increase the value of the first char in the first string. Not what rje intended. You need to use an index. Assuming that the strings do not fit within 256 bytes you could use indirect indexed addressing mode, for example: lda #<text sta $30 lda #>text sta $31 ldy #0 loop: lda ($30),y cmp #'*' beq eof jsr $ffd2 iny bne loop inc $31 jmp loop eof: rts
  15. I haven't done the math to tell which method is faster. The methods described in the articles are general and scales well. My gut feeling is that they are more effective when dealing with large numbers (more than 16 bits). I'm using those functions on 32 bit numbers. First and foremost because of the beauty of the design
  16. If I understand your code it's a repeated subtraction method. I've found some other interesting methods, which have worked nicely. On converting from binary to decimal: http://www.6502.org/source/integers/hex2dec-more.htm On converting from decimal to binary: https://www.atarimagazines.com/compute/issue17/221_1_A_GENERAL_PURPOSE_BCD-TO-BINARY_ROUTINE.php
  17. Hi. Version 0.2.1 uploaded. Some bug fixes, especially the automatic word wrap function that wasn't working. I've written a short user manual that is also available on the download page. And I finally got the "Try it now" button to work. However, there are some differences. For instance not all Ctrl+key commands are recognized when you run the program in the online emulator. I think it's still best to download the program and run it in your emulator locally. And one more thing I forgot to mention. I've implemented a defragmentation routine that runs in the "background". Actually it's invoked to defrag one memory page each interrupt if there is no user input to handle. The memory model discussed at the beginning of this thread makes it possible to edit large files. The downside is that there is a lot of unused space, especially if you back and forth in the file editing it. The defrag routine takes care of that problem.
  18. I agree that it's unlikely that the hardware chip select wraps around to skip unpopulated memory. At the beginning of this thread, I also assumed that we would see random, ff or 0 on the data bus when reading unpopulated memory. I guess we just have to wait and see when the board is done. Reading a recent post by @Lorin Millsap elsewhere on this site, it is a work in progress. Maybe the Board works in mysterious ways
  19. What happens if you reduce the clock speed?
  20. Version 0.2.0 of X16 Edit now released. It supports word wrap. Word wrap is turned off by default. Enable by pressing Ctrl+Z. X16 Edit is now feature complete as I've planned version 1.0. I will continue cleaning the code, fixing bugs, and improving the user interface.
  21. You will be able to turn it on and off (Ctrl+Z). When turning on, you are prompted to set at what column to wrap.
  22. An actual line feed char is inserted when wrapping a long line. GNU Nano's long line wrapping function (ESC+L) does this too. I had a discussion with @BruceMcF above in this thread on the design of a word wrap function. Apparently, his favorite editor from the past, VDE, also did this. This is my second attempt to create a text editor for X16. My first program had word wrap calculated on the fly without inserting line feed chars. However, this became very complex and error prone, and I finally had to discard that work. Based on my first experience, I had decided not to do word wrap, but Bruce talked me into it. I think the word wrap function is a nice addition and that it will be sufficiently usable. I'm not making a word processor. The next version of X16 Edit will have word wrap, and then I will consider the program to be feature complete. Thereafter I will focus on bug fixes and minor improvements to the user interface. I think version 0.1.1 already works pretty well. If you try it, please let me know what you think.
  23. I've started working on a simple word wrap function. It's very rudimentary: If you type a letter at the set right margin, it will wrap at the previous blank space. It will not wrap or rewrap text in any of these cases: If you insert text at the beginning of the line, even if the length of the line goes beyond the set margin If you delete a line feed marker Is it good enough? Enclosed also a short video demonstrating what I'm talking about. Skärminspelning 2020-10-11 kl. 15.45.37.mov
  24. I made a small test program that writes to file. One file was closed with CLOSE+CLRCHN and the other with CLRCHN+CLOSE. Both alternatives seem to work without issues. It might just be a matter of taste in what order you call the functions. To me it's more logical to call CLRCHN last, as it's not paired to one CHKIN or CHKOUT invocation - it resets all I/O channels. To clarify what I mean: say that you at the same time open one file for reading and another file for writing to copy the content of the first file to the second file. It's more logical to first close those files before you invoke CLRCHN. There's no reason to say that Heimarck and Parrish misunderstood the Kernal. Reading their book, it's obvious that they knew the Kernal in great detail.
  25. I found a book online that describes the use of CLALL, CLOSE, and CLRCHN in more depth: "Machine language routines for the Commodore 64 and 128" by Todd D. Heimarck and Patrick Parrish, 1987. On page 63 they talk about CLALL. As you may see by disassembling the Kernal in the X16 monitor, CLALL only resets the open file counter to 0 and then falls through to CLRCHN. The authors confirm that the routine, despite its name, doesn't close any files, and that the routine is not safe to use when working with files over the serial bus. If you disassemble the CLOSE routine, you can see that it sends commands over the serial bus to notify the other device. To understand what those commands are, you need to dig deeper into the functioning of the C64 serial bus, which I haven’t done. https://archive.org/details/Compute_s_Machine_Language_Routines_for_the_Commodore_64_and_128/page/n69/mode/2up On page 172, there is a code example on how to close a file. That routine calls CLOSE first and then CLRCHN. https://archive.org/details/Compute_s_Machine_Language_Routines_for_the_Commodore_64_and_128/page/n177/mode/2up To wrap it up: Don't use CLALL to close files. Use CLOSE. It’s normal to call CLOSE first and CLRCHN second. It would be interesting to test how a device reacts to CLOSE if CLRCHN was called first, especially when writing to a file. My limited understanding of CLRCHN is that is sends UNTALK/UNLISTEN to all devices on the bus, and that could affect how a device handles a subsequent CLOSE. I might do a small test and see if you get file corruption or other problems, or if it works fine either way. Have a nice weekend.
  • Create New...

Important Information

Please review our Terms of Use