none
What's a PC Engine?
Posts: 4
|
Post by none on Jun 8, 2023 19:28:47 GMT
Hi, everyone! I'm currently trying to learn about PC Engine homebrew development, and decided to come here to show what I've done so far and ask for some help or advice about a problem I'm currently having. My progress so far
Here's a link to the source code of what I currently have.I decided to go with WLA-DX for this for a few reasons: - Good documentation available for it.
- Popular enough to be widely used or mentioned in other platforms.
- It's actively maintained on Github.
However, it has one big tradeoff: - There are no resources for PC Engine written for it.
I decided to start it all from scratch then, just to see how far I could get with this. It took me one week to read all the guides and understand how everything works, but at least I got something to use as a reference now. My idea is to have a " Hello World" for WLA-DX written in a single file, with everything properly commented and with at least one of each step included. I don't plan to cover strings, or collision detection, or tile/sprite handling yet. Just the basic resources needed for a game: inserting graphics, adding a single tile/sprite, controls, playing a single sound sample... So far I have: - Setting up palettes.
- Setting up a tile.
- Setting up a sprite.
What's currently missing: - Controls (to move the sprite).
- Sound (just one sample, and one tune).
- Vsync/Vblank.
The problems I'm having
My current problems so far with this code: - Random crashes on MAME.
- Doesn't work on Mednafen.
MAME
So far I've been using MAME for testing because of the debugger. It's easy to step through the code, and the memory viewer helped me a lot while trying to understand how the SATB worked. However, MAME is weird in some ways. Sometimes it "glitches out" and starts code at a wrong location, sometimes even executing garbage or a bunch of " brk" instructions... ...and it randomly crashes sometimes for reasons I can't really understand: When it does work, though, it seems to run just fine, displaying the tile and sprite correctly: Maybe it's just a MAME issue? I'm currently using MAME 0.255.
Mednafen
At some point, though, I decided to download Mednafen and see if the same weird behavior I had in MAME would happen there too. So I ran my ROM there and... Nothing. Just a black screen. However, the loop I made which keeps counting 1 to $2000 works! It just doesn't display the graphics: But here's something interesting: Chris Covell has a couple of tutorials for PC Engine, all with source and ROMs included. The simplest one is the "rainbow" effect, which keeps updating the palette at runtime. This effect can be added into SUBROUTINE_START: ; Subroutine responsible for the game loop. SUBROUTINE_START: - lda $2000 adc #1 sta $2000 @loop: stz $0402 stx $0403 sta $0404 sty $0405
ina bne @next iny @next: pha pla pha pla ; end
bra - ; end
This is how appears on MAME: And this is how it appears on Mednafen: Am I missing something there? What I'm doing wrong? I'm currently using Mednafen 1.31.0.
Ares
I'm currently using Ares 132. At this point, I got desperated. Mednafen seems to be a common recommendation for PC Engine games, which got me thinking if the instructions I've been following were actually correct, or if there's something there missing. Since there's a draw between MAME and Mednafen, I looked for another emulator to be the "tie-breaker". The Emulation General Wiki mentions Ares as a recommended emulator for PC Engine, even stating it as cycle accurate. So I downloaded it, and... It works, just like MAME! And it doesn't randomly crash! And the rainbow effect works as well: So... who's the right or the wrong on this one? I don't own a PC Engine, by the way, so I can't test this on real hardware either. I assume it must be something related to Vsync/Vblank, which is why I marked it as bold on the list shown previously. But none of the sources I used for learning seem to cover that in detail. They either skip this part, or just include startup.asm and go with it. This latter having so much things going on that I just couldn't even read, let alone rewrite it on WLA-DX's syntax.
Help needed
Could anyone please help me on this? Any advice on what should I do next? Although WLA-DX doesn't seem to be a popular choice for PCE development, I'm quite happy with how far I went with it. Having almost literally started with "nothing" and scrapping through reference guides and memory addresses was very challenging for me, who never went so far into assembly language before that. But I also got a bit frustrated by these issues. After spending so much time digging through resources to have something to work, it's very frustrating to get through issues like this in MAME/Ares/Mednafen. I'm hoping that my code is at least accurate.
|
|
|
Post by dshadoff on Jun 8, 2023 19:56:06 GMT
Well, I don't know anything about WLA-DX, but I can tell you that one major problem is that none of your video display registers are set up, so Mednafen is correct in not displaying anything. This also means that all of the other emulators are not properly emulating the hardware, at least in terms of boot conditions.
If you ran this on a real PC Engine via a direct cartridge, this would also not display properly (but what you actually see on screen may be different).
However, interestingly... if you were to run it from something like a TurboEverDrive or a SHDS3 or similar multi-ROM system, it might actually display something... but this would be because the display registers are initialized by their boot menu programs, and are generally left in that initialized state when they jump to the ROM files that are selected.
I hate to break it to you, but you are going to have to invest the time in understanding the very well-documented startup.asm code... this was one of the most significant areas of investment which were made in HuC in order to make development easier.
|
|
|
Post by dshadoff on Jun 11, 2023 14:59:20 GMT
|
|
none
What's a PC Engine?
Posts: 4
|
Post by none on Jun 12, 2023 22:09:01 GMT
Well, I don't know anything about WLA-DX, but I can tell you that one major problem is that none of your video display registers are set up, so Mednafen is correct in not displaying anything. This also means that all of the other emulators are not properly emulating the hardware, at least in terms of boot conditions. If you ran this on a real PC Engine via a direct cartridge, this would also not display properly (but what you actually see on screen may be different). However, interestingly... if you were to run it from something like a TurboEverDrive or a SHDS3 or similar multi-ROM system, it might actually display something... but this would be because the display registers are initialized by their boot menu programs, and are generally left in that initialized state when they jump to the ROM files that are selected. I hate to break it to you, but you are going to have to invest the time in understanding the very well-documented startup.asm code... this was one of the most significant areas of investment which were made in HuC in order to make development easier. Well... that was disappointing. But also a relief. Since both MAME and Ares were working, I was planning to just ignore Mednafen and continuing on the other missing parts, thinking that it was probably just a minor issue. It was just one emulator out of many others, after all. As it turns out, Mednafen seems to be the only one that emulates the boot process correctly, So I guess I gotta have to test on it, too (so far I was only testing on MAME). Chris Covell's examples include a minimal startup.asm, so I decided to download one of the very first examples and try to read it to see if I could understand what happens there. Although that code itself looks short, it took me a considerable amount of time to understand how that works properly. My biggest issues were the shortened names for certain values and the pseudo-instructions (macros disguised as instructions), like stw. But I managed to find the missing parts and now it finally works on Mednafen: Current progressAfter finally have the sprite to appear, I tried to get started with player controls to move it. I wanted to save each input individually on RAM, but got frustrated with how multitap works and left that to just read from one controller instead, at least for now. Then, I tried to just make it move automatically: It moves too fast, though. I didn't figure out how to do the "wait for vblank" thing yet.
|
|
|
Post by elmer on Jun 14, 2023 15:54:21 GMT
Congratulations on getting as far as you have! While you can continue using WLA-DX if you wish, there are distinct advantages to using PCEAS for PC Engine development, especially when handling multiple banks of code and data, which is something that's very important on the PC Engine. Chris's tutorials and examples are an excellent resource, but I'd strongly recommend that you consider using the newer version of PCEAS that's including in the HuC distribution (https://github.com/pce-devel/huc/releases/tag/master). You might also like to look at my "Getting Started" assembly-language projects within HuC (https://github.com/pce-devel/huc/tree/master/examples/asm/elmer). They were written with the intent to be easier to understand than startup.asm and the old MagicKit libraries, but I suspect that I may have ended up failing in that goal. You might also wish to switch from using that stock version of Mednafen for the upgraded PCE-Devel version here (https://github.com/pce-devel/mednafenPceDev/releases), your eyestrain should be considerably reduced!
|
|
none
What's a PC Engine?
Posts: 4
|
Post by none on Jun 20, 2023 9:39:50 GMT
Congratulations on getting as far as you have! While you can continue using WLA-DX if you wish, there are distinct advantages to using PCEAS for PC Engine development, especially when handling multiple banks of code and data, which is something that's very important on the PC Engine. Chris's tutorials and examples are an excellent resource, but I'd strongly recommend that you consider using the newer version of PCEAS that's including in the HuC distribution (https://github.com/pce-devel/huc/releases/tag/master). Thanks for the cheers up! Apart from a few minor issues, so far my experience with WLA-DX has been positive. It's inevitable that I will end up hitting a wall at some point, though, so I might have to switch to PCEAS later on. But I'm curious to see how far I can go with WLA-DX before doing that. You might also like to look at my "Getting Started" assembly-language projects within HuC (https://github.com/pce-devel/huc/tree/master/examples/asm/elmer). They were written with the intent to be easier to understand than startup.asm and the old MagicKit libraries, but I suspect that I may have ended up failing in that goal. Great resources, they're very well organized in comparison to other examples I found! I took a look at bare-startup.asm and joypad.asm to see how it was compared to the common startup.asm and if I could understand anything from it. As some kind of feedback, I will leave some of my progress which I made by reading them. Bare startupbare-start.asm is easier to understand in comparison to the common startup.asm, mainly due to it's simplicity. In a way, it's similar to the startup.asm found on first examples of Chris Covell's tutorials, but the code is extensively commented, explaining what each part does in a "step-by-step" way. There are some parts used there that I don't have in my startup code. I forgot to handle soft resets. stz TIMER_CR ; HW reset already does these, ; line 148 stz IRQ_ACK ; but this may be a reset from ; line 149 stz IRQ_MSK ; software (i.e. joypad). ; line 150
lda #%11111 ; Enable joypad soft-reset. ; line 166 sta joyena ; line 167 Still having a hard time understanding what's going on with those interrupt handlers, though. On my startup code, I just disable them with this. lda %00000111 ; IRQFlags(1, 1, 1) sta $1402 ; IO_IRQ_DISABLE Without this, the code randomly jumps around without even letting the main loop to finish. And I don't know how to control them. What's the difference between IRQ1 and IRQ2? What does the timer do with any of these? How can I handle them without breaking the main loop? And how can I keep track of them? How can I signal that the frame is over at the end of the main loop? To go even further, I wish I could have something like this: VDCHook() { if(vsync < 16) { background.x = 0; } else { background.x = scroll.x; } }
loop() { scroll.x++; vblank(); } That would allow me to have one section for HUD, and other section for tilemap/background. And while I still hadn't figure out how to properly end a frame, I was able to control the framerate by delaying the loop manually, but I'm not sure if that's the correct way of doing it. JoypadInitially, I found joypad.asm to be quite confusing: it tries to provide support for every controller, but you'll probably only need 1 or 2. I guess it's not meant to be read entirely, but rather you just look for the individual parts for the controllers you want, and take it. While my code already had input working on a single port, I still hadn't figure out how multitap works. That wouldn't be a problem, until I found out that, except for MAME, every emulator seems to include multitap support by default, without any option to turn it off. So you either support multitap, or have no input at all on most emulators. The SUPPORT_2BUTTON section helped me to understand how to fetch input from the multitap, and I finally got it working. My code is also a little bit different: I'm bitshifting each bit separately, while the joypad.asm uses a bitmask. But other than that, it seems to be working fine. One way to improve readability would be to have some sort of standard "doc comments" for each macro/constant, and a code editor which could display them when you move the cursor over (it could be done as a plugin/extension). That's because there are too many files to keep track of, which makes it harder to check how one specific part is implemented. You might also wish to switch from using that stock version of Mednafen for the upgraded PCE-Devel version here (https://github.com/pce-devel/mednafenPceDev/releases), your eyestrain should be considerably reduced! I'll be using this one for testing now, thanks! SoundSo far I managed to get almost everything necessary to make a simple game: tiles, sprites, and input. The only resource that's missing now is sound. There was one example on ChibiAkumas tutorials, but I wasn't able to do much with it. The sound is very irritating, and it only works by constantly writing 32 bytes of data each frame. Actually, I was even wondering how are these 5 bits stored... 1 byte 2 bytes 3 bytes [00011111] [00022222] [00033333]
1 byte 2 bytes 3 bytes 4 bytes [11111][222] [22][33333][4] [4444][5555] [5] ...
How do I control the PSG? Any guides/tutorials for learning? Is there any concept of ADSR (Attack, Decay, Sustain, Release) for it? How can I convert/create a tone for it? Can I just play a sample for a certain amount of time without having to constantly write the same data? The ArchaicPixels wiki says that it's possible to convert samples to PC Engine using sox, but I don't know how to actually play it, and it seems to be something specific to the CD drive. I also found something about a HES format, but I'm not sure if that's what I'm looking for.
|
|
|
Post by dshadoff on Jun 20, 2023 16:26:53 GMT
It sounds to me like you are trying to program the machine on a whole new assembler without first understanding the underlying hardware (which of course, is necessary if you are programming in assembly language).
In order to understand Timer, IRQ1, and IRQ2, it’s best to see how they are used by other example programs, and/or the libraries which were written for this purpose…
I don’t understand what you mean by “While my code already had input working on a single port, I still hadn't figure out how multitap works. That wouldn't be a problem, until I found out that, except for MAME, every emulator seems to include multitap support by default, without any option to turn it off.”… ->having emulator support for multitap on or off shouldn’t have any impact on your code if you are polling only one joypad. -> also, what do you mean, “on a single port” ? There is only one port on the PC Engine, with joypads 2 onward read sequentially through the same port.
Likewise, the phrase “ I'm bitshifting each bit separately” sounds strange, since the data comes in 4 bits at a time…
Perhaps you have worked on a different architecture previously, and are assuming that all machines have all the same base concepts. In order to help you understand these concepts, it might be useful for you to state your assumptions (and previous console knowledge) as part of the question… “I am doing <x> on this port, and expecting to get a result of <y>… does it not work the same way as a SuperFamicom ?”
Finally, ADSR envelopes are managed by a music player which would wake up every interrupt (either vsync or timer), and adjust position within the envelope definition, and adjust volumes accordingly. It’s software, not hardware. And ADPCM is supported only on CDROM units, which may or may not match your expectations.
|
|
|
Post by elmer on Jun 20, 2023 17:00:27 GMT
Still having a hard time understanding what's going on with those interrupt handlers, though. On my startup code, I just disable them with this. lda %00000111 ; IRQFlags(1, 1, 1) sta $1402 ; IO_IRQ_DISABLE Without this, the code randomly jumps around without even letting the main loop to finish. And I don't know how to control them. AFAIK there are no hardware interrupts enabled on HuCARD startup after power-on, so if you're getting random interrupts firing ... that's because you've enabled them. As it is, after a quick look at your code on github, you've not enabled either the VBL or RCR interrupts on the VDC, and you've not enabled interrupts on the CPU anyway (with a CLI), so whatever you're seeing doesn't *sound* like it's interrupt-related. Although ... ; Initalize stack (stack pointer) on I/O mapper ($FF). ldx #MPR_IO ... does not do whatever it is that you think that it is supposed to do. Also, not that you're at the point where this matters yet, but you've got some of the bits wrong in your VDCControlFlags() function, and y'all need to check that against the VDC manual. Another problem for that future is that you've broken the joypad reading code by splitting it into 2 parts without understanding how and why it works, and anyway NOP is 2-cycles, not 1-cycle. But I think that one of the biggest problems that I'm seeing for the future, and actually getting the program to run on anything but an emulator, is that you're assuming that both RAM and VRAM are initialized to zero on power-up, and that's just not the case on real hardware. If you want the RAM or VRAM cleared, then you MUST do it yourself in your startup code. What's the difference between IRQ1 and IRQ2? What does the timer do with any of these? How can I handle them without breaking the main loop? And how can I keep track of them? How can I signal that the frame is over at the end of the main loop? You don't synchronize the video frame to the main loop, you synchronize the main loop to the video frame. You can think of the video frame as a separate processor/thread that runs at a constant 60Hz-per-frame. You can get the VDC to tell the CPU when it's at a certain line, or when the frame is finished, by having the VDC trigger an interrupt, but the CPU can't tell the VDC exactly when to start displaying a new frame, the VDC timing is independant. That's how all video-game consoles work. IRQ1 comes from the VDC chip, and IRQ2 comes from the CD-ROM Interface. The TIMER is embedded in the CPU. These are listed in bare-startup.asm. As to how you actually enable, acknowledge, and just generally *use* them ... that's what the manuals and example code are for. Your question is so general that I don't know how to respond in a helpful way other than saying that, and it really sounds as though you may need to do some basic learning about what interrupts are. Here's the section on interrupts in Zaks.
|
|
none
What's a PC Engine?
Posts: 4
|
Post by none on Jun 20, 2023 23:33:36 GMT
It sounds to me like you are trying to program the machine on a whole new assembler without first understanding the underlying hardware (which of course, is necessary if you are programming in assembly language). In order to understand Timer, IRQ1, and IRQ2, it’s best to see how they are used by other example programs, and/or the libraries which were written for this purpose… It's painful to admit, but that is true. I thought it would be relatively simple to learn, and that I could achieve something by following some guides or the memory map. In a way, I actually did achieve this in some part, but that took me a lot longer than I initially expected. I don’t understand what you mean by “While my code already had input working on a single port, I still hadn't figure out how multitap works. That wouldn't be a problem, until I found out that, except for MAME, every emulator seems to include multitap support by default, without any option to turn it off.”… ->having emulator support for multitap on or off shouldn’t have any impact on your code if you are polling only one joypad. -> also, what do you mean, “on a single port” ? There is only one port on the PC Engine, with joypads 2 onward read sequentially through the same port. When trying to poll the joypad for the first time, I was saving them on RAM to watch their states, but noticed that they were being saved in an unordered way. They kept "cycling" through each memory location dedicated for them each frame, with no way of keeping track of them. Since you have to poll each joypad sequentially, my first guess was that was something to do with multitap. On MAME, it's possible to change the ports on Slot Devices. Multitap was enabled by default. When I turned it off, it started to read the input! However, to get it working properly, along with multitap, I moved the polling code to the loop subroutine and changed the instructions used to delay the ticks. Then it worked! lda #1 sta IO_IRQ_JOYPAD lda #3 sta IO_IRQ_JOYPAD
pha pla nop
I assumed they were only required to be written once, when they should be written constantly. And looks like the last bit says which controller port is being fetched. And by "on a single port", I mean "only one controller plugged into the only port available on PC Engine". Likewise, the phrase “ I'm bitshifting each bit separately” sounds strange, since the data comes in 4 bits at a time… On bare-startup.asm, you can find this bitmask:
bit_mask: db $01,$02,$04,$08,$10,$20,$40,$80 I suppose it's meant to do something like this:
x & bit_mask[0-8] While I'm doing the equivalent of this:
(x >> 0-8) & 1 That's what I was trying to say with "bitshifting each bit separately". I should've used a better term. And yes, only the first 4 bits contain the input, but they come in bytes, so I split and store them separately to read later. Perhaps you have worked on a different architecture previously, and are assuming that all machines have all the same base concepts. In order to help you understand these concepts, it might be useful for you to state your assumptions (and previous console knowledge) as part of the question… “I am doing <x> on this port, and expecting to get a result of <y>… does it not work the same way as a SuperFamicom ?” Okay, so maybe I should give some background first... I learned a bit of 6502 through Commodore 64. I didn't learn all of it, though, mostly because the interest quickly faded away. But I managed to learn a few things from it, like branching, loops, printing/drawing on screen and how to handle data structures on memory. - I wrote some small VMs, with my own instruction sets. Although completely unrelated, these were useful for me to experiment with a few other concepts on my own, like bankswitching and interrupts/syscalls.
These are the most significative. I think this should be enough to reflect how much knowledge I have over assembly programming in general. My initial assumption was that a game loop would look more or less like this: loop: ; game logic nmi jmp loop That's how I implemented interrupts on my VMs: once you request a interrupt, the CPU stops until a response is received. Then, the response would be saved somewhere (either a fixed memory location, or an extra register) and the code would continue from where it was. For vsync/hsync, I was expecting to either have this value constantly updated somewhere on a memory location, or manually requesting interrupts within the loop to check where it was. I'm not sure if that will help with anything related to PCE, but maybe it can help to receive proper advice on where I should start, or what I should've learned first. Finally, ADSR envelopes are managed by a music player which would wake up every interrupt (either vsync or timer), and adjust position within the envelope definition, and adjust volumes accordingly. It’s software, not hardware. And ADPCM is supported only on CDROM units, which may or may not match your expectations. It looks silly, but I really thought the audio chip would do that for me. That was good to know. AFAIK there are no hardware interrupts enabled on HuCARD startup after power-on, so if you're getting random interrupts firing ... that's because you've enabled them. As it is, after a quick look at your code on github, you've not enabled either the VBL or RCR interrupts on the VDC, and you've not enabled interrupts on the CPU anyway (with a CLI), so whatever you're seeing doesn't *sound* like it's interrupt-related. I kept testing that locally, so I never updated the code with interrupts on. Whenever the code doesn't work or breaks, I restore it. Although ... ; Initalize stack (stack pointer) on I/O mapper ($FF). ldx #MPR_IO ... does not do whatever it is that you think that it is supposed to do. To be honest, I don't know exactly what this is supposed to do. At some point, I removed it from the code, but this same txs can be found on startup.asm aswell, so I ended up adding it back, just in case it would be needed for something. Also, not that you're at the point where this matters yet, but you've got some of the bits wrong in your VDCControlFlags() function, and y'all need to check that against the VDC manual. That's good to know. Another problem for that future is that you've broken the joypad reading code by splitting it into 2 parts without understanding how and why it works, and anyway NOP is 2-cycles, not 1-cycle. Sorry, I didn't update the code. I'm currently using this for polling the joypads: lda #1 sta IO_IRQ_JOYPAD lda #3 sta IO_IRQ_JOYPAD pha pla nop But I think that one of the biggest problems that I'm seeing for the future, and actually getting the program to run on anything but an emulator, is that you're assuming that both RAM and VRAM are initialized to zero on power-up, and that's just not the case on real hardware. If you want the RAM or VRAM cleared, then you MUST do it yourself in your startup code. Also good to know, I was looking to get other things done and forgot that. You don't synchronize the video frame to the main loop, you synchronize the main loop to the video frame. You can think of the video frame as a separate processor/thread that runs at a constant 60Hz-per-frame. You can get the VDC to tell the CPU when it's at a certain line, or when the frame is finished, by having the VDC trigger an interrupt, but the CPU can't tell the VDC exactly when to start displaying a new frame, the VDC timing is independant. That's how all video-game consoles work. IRQ1 comes from the VDC chip, and IRQ2 comes from the CD-ROM Interface. The TIMER is embedded in the CPU. These are listed in bare-startup.asm. As to how you actually enable, acknowledge, and just generally *use* them ... that's what the manuals and example code are for. Your question is so general that I don't know how to respond in a helpful way other than saying that, and it really sounds as though you may need to do some basic learning about what interrupts are. Here's the section on interrupts in Zaks. Thanks for all the advice! I'm sorry if any of my answers look too amateurish or silly, but I think it was important to clarify my points and being honest about what I was doing (or trying to do). It actually got me thinking here on what I've been doing. Looking on my own progress, I think I made some serious mistakes: - Trying to do too many things at the same time, without any previous knowledge at all.
- Assuming that just "learning assembly" and having a list of memory addresses would be enough, without actually understanding how the machine works.
- Failing to read documentation and/or hardware reference correctly.
- Choosing an unsupported tool to get started.
And sorry if this somehow ended up wasting someone's time here. I thought I was doing fine and wasn't even aware that some of my questions were so basic. Given the answers, I guess It will be better for me to stop, evaluate what I done so far, then take some time to think what should I do next.
Regardless of the outcome, I'm still surprised to see how far I actually went with this. Again, thanks for all the advice and for taking your time to give me some directions!
|
|
|
Post by dshadoff on Jun 21, 2023 3:03:09 GMT
Our responses weren't meant to discourage - simply to identify that there was a gap in communications related to the how the hardware works. I'm satisfied that you can overall deal with assembly language in general, but the hardware needs to be understood.
A couple of points:
Well, sort of.
More like:
loop:
; game logic
(wait for vsync) ; basically in a loop, polling the status register of the VDC
jmp loop
About the joypads:
Again, partly correct.
It should be more like:
lda #1 sta IO_IRQ_JOYPAD lda #3 sta IO_IRQ_JOYPAD ; must always, for joypad #1, produce a high-low pulse on the CLEAR/RESET line. lda #1 sta IO_IRQ_JOYPAD ; this brings the CLEAR back to 0, while still enabling the read of the first half of data pha pla nop (read $1000) stz IO_IRQ_JOYPAD pha pla nop (read $1000)
For subsequent joypads, you can skip the part about writing the value 3. However, for subsequent reads of the first joypad, you need to do the above again.
|
|
|
Post by elmer on Jun 22, 2023 16:59:23 GMT
Looking on my own progress, I think I made some serious mistakes: - Trying to do too many things at the same time, without any previous knowledge at all.
- Assuming that just "learning assembly" and having a list of memory addresses would be enough, without actually understanding how the machine works.
- Failing to read documentation and/or hardware reference correctly.
- Choosing an unsupported tool to get started.
I totally understand the fun/desire of just jumping in at the deep end, but hopefully you've learned some of the pitfalls of that approach. You still achieved a lot in a small amount of time, but now you need to decide how and if you'll choose to tackle the problem from a different perspective ... I do hope that you choose to keep on going. Honestly, I suggest that you do what we *all* did to learn this stuff back-in-the-day, and that's to take a *working* example, make *sure* that you can build that working example, and then start slowly editing it and changing things so that it does what you want. That's the easiest way to learn, and that's why folks like Chris and I post example projects. Taking my "rom-core-hello" project (the simplest), and just replacing the complex-and-difficult-to-understand "core" library with the "bare-startup" library should take you about 5 minutes ... the libraries are designed to provide the same runtime conditions to HuCARD projects, it's just that the "core" library is *much* more complex because it has to deal with CD/SCD/TED2 as well. Editing an example project and collecting all of the functions used into a single source file would make it easier for you to see what is actually used, and again, it would only take a few minutes. Then you could start editing things to do what you want and see when it breaks. But if you're going to continue, and want to ask for help, then you *need* to upload your *current* code to where folks can see it. We can't help if we can't build what you're building, and see where it breaks.
|
|